This commit is contained in:
Jackzie 2024-09-22 14:27:39 -05:00
parent 1a1663ba37
commit ed383ecc91
14 changed files with 553 additions and 46 deletions

View file

@ -5,10 +5,11 @@
#define PLUGIN_VERSION "1.0"
#define PRECACHE_SOUNDS_COUNT 4
#define PRECACHE_SOUNDS_COUNT 5
char PRECACHE_SOUNDS[PRECACHE_SOUNDS_COUNT][] = {
"custom/xen_teleport.mp3",
"custom/mariokartmusic.mp3",
"custom/airhorn.mp3",
"custom/spookyscaryskeletons.mp3",
"custom/wearenumberone2.mp3",
};

View file

@ -248,6 +248,14 @@ public void Event_L4D2_Death(Event event, const char[] name, bool dontBroadcast)
if(IsFakeClient(attacker)) GetClientName(attacker, attackerName, sizeof(attackerName));
else GetClientAuthId(attacker, AuthId_Steam2, attackerName, sizeof(attackerName));
if(GetClientTeam(attacker) == 2) {
char weaponName[32];
event.GetString("weapon", weaponName, sizeof(weaponName));
if(weaponName[0] != '\0') {
AddLogCustom("STATE", attackerName, victimName, "\"%L\" killed \"%L\" with \"%s\"", attacker, victim, weaponName);
return;
}
}
AddLogCustom("STATE", attackerName, victimName, "\"%L\" killed \"%L\"", attacker, victim);
} else {
AddLogCustom("STATE", "", victimName, "\"%L\" died", victim);
@ -267,7 +275,15 @@ public void Event_L4D2_Incapped(Event event, const char[] name, bool dontBroadca
if(attacker > 0 && attacker != victim) {
if(IsFakeClient(attacker)) GetClientName(attacker, attackerName, sizeof(attackerName));
else GetClientAuthId(attacker, AuthId_Steam2, attackerName, sizeof(attackerName));
if(GetClientTeam(attacker) == 2) {
char weaponName[32];
event.GetString("weapon", weaponName, sizeof(weaponName));
if(weaponName[0] != '\0') {
AddLogCustom("STATE", attackerName, victimName, "\"%L\" incapped \"%L\" with \"%s\"", attacker, victim, weaponName);
return;
}
}
AddLogCustom("STATE", attackerName, victimName, "\"%L\" incapped \"%L\"", attacker, victim);
} else {
AddLogCustom("STATE", "", victimName, "\"%L\" was incapped", victim);

View file

@ -203,6 +203,7 @@ void LoadFolder(ArrayList parent, const char[] rootPath) {
DirectoryListing listing = OpenDirectory(rootPath);
if(listing == null) {
LogError("Cannot open \"%s\"", rootPath);
return;
}
while(listing.GetNext(buffer, sizeof(buffer), fileType)) {
if(fileType == FileType_Directory) {

View file

@ -135,7 +135,7 @@ Action Command_DoAHat(int client, int args) {
char sizeStr[4];
GetCmdArg(2, sizeStr, sizeof(sizeStr));
float size = StringToFloat(sizeStr);
if(size == 0.0) {
if(size <= 0.0) {
ReplyToCommand(client, "[Hats] Invalid size");
return Plugin_Handled;
}
@ -335,7 +335,12 @@ Action Command_DoAHat(int client, int args) {
} else {
// Find a new hatable entity
int flags = 0;
entity = GetLookingEntity(client, Filter_ValidHats);
if(args > 0 && isForced) {
char arg[16];
entity = GetCmdArgInt(1);
} else {
entity = GetLookingEntity(client, Filter_ValidHats);
}
if(entity <= 0) {
PrintCenterText(client, "[Hats] No entity found");
return Plugin_Handled;

View file

@ -0,0 +1,427 @@
int SpawnCar(VariantEntityData entity) {
if(entity.model[0] == '\0') {
LogError("Missing model for entity with type \"%s\"", entity.type);
return -1;
}
PrecacheModel(entity.model);
int vehicle;
if(StrEqual(entity.type, "_car_alarm")) {
vehicle = SpawnAlarmCar(entity.model, entity.origin, entity.angles, entity.color);
return vehicle;
}
char glassModel[64];
strcopy(glassModel, sizeof(glassModel), entity.type);
ReplaceString(glassModel, sizeof(glassModel), ".mdl", "_glass.mdl");
if(StrEqual(entity.type, "_car_physics")) {
vehicle = CreateProp("prop_physics", entity.model, entity.origin, entity.angles);
} else {
vehicle = CreateProp("prop_dynamic", entity.model, entity.origin, entity.angles);
}
if(PrecacheModel(glassModel)) {
int glass = CreateProp(glassModel, entity.model, entity.origin, entity.angles);
SetVariantString("!activator");
AcceptEntityInput(glass, "SetParent", vehicle);
}
SetEntityRenderColor(vehicle, GetRandomInt(0, 255), GetRandomInt(0, 255), GetRandomInt(0, 255));
return vehicle;
}
/**
// ====================================================================================================
:::BEGIN::: -> Source Code (with changes) from:
* DieTeetasse - [L4D1&2] Spawn Alarmcars plugin https://forums.alliedmods.net/showthread.php?t=139352
* Marttt - [L4D1 & L4D2] Replace Cars Into Car Alarms plugin https://forums.alliedmods.net/showthread.php?p=2731868
// ====================================================================================================
*/
/****************************************************************************************************/
#define DISTANCE_FRONT 101.0
#define DISTANCE_SIDETURN 34.0
#define DISTANCE_UPFRONT 29.0
#define DISTANCE_BACK 103.0
#define DISTANCE_SIDE 27.0
#define DISTANCE_UPBACK 31.0
#define SOUND_CAR_ALARM "vehicles/car_alarm/car_alarm.wav"
#define SOUND_CAR_ALARM_CHIRP2 "vehicles/car_alarm/car_alarm_chirp2.wav"
#define COLOR_YELLOWLIGHT "224 162 44"
#define COLOR_REDLIGHT "255 13 19"
#define COLOR_WHITELIGHT "252 243 226"
#define ALARMCAR_GLOW_SPRITE "sprites/glow.vmt"
int SpawnAlarmCar(const char[] model, float vPos[3], float vAng[3], int color[4] = { 255, 255, 255, 255})
{
PrecacheModel(model);
PrecacheModel(ALARMCAR_GLOW_SPRITE, true);
PrecacheSound(SOUND_CAR_ALARM, true);
PrecacheSound(SOUND_CAR_ALARM_CHIRP2, true);
char carName[64];
char glassOnName[64];
char glassOffName[64];
char timerName[64];
char alarmSoundName[64];
char chirpSoundName[64];
char lightsName[64];
char headlightsName[64];
char remarkName[64];
char gameEventName[64];
// create car
int carEntity = CreateEntityByName("prop_car_alarm");
FormatEx(carName, sizeof(carName), "randomizer_car_%d", carEntity);
FormatEx(glassOnName, sizeof(glassOnName), "randomizer_car_glasson_%d", carEntity);
FormatEx(glassOffName, sizeof(glassOffName), "randomizer_car_glassoff_%d", carEntity);
FormatEx(timerName, sizeof(timerName), "randomizer_car_alarmtimer_%d", carEntity);
FormatEx(alarmSoundName, sizeof(alarmSoundName), "randomizer_car_alarmsound_%d", carEntity);
FormatEx(chirpSoundName, sizeof(chirpSoundName), "randomizer_car_chirpsound_%d", carEntity);
FormatEx(lightsName, sizeof(lightsName), "randomizer_car_lights_%d", carEntity);
FormatEx(headlightsName, sizeof(headlightsName), "randomizer_car_headlights_%d", carEntity);
FormatEx(remarkName, sizeof(remarkName), "randomizer_car_remark_%d", carEntity);
FormatEx(gameEventName, sizeof(gameEventName), "randomizer_car_gameevent_%d", carEntity);
char tempString[128];
DispatchKeyValue(carEntity, "targetname", carName);
DispatchKeyValue(carEntity, "model", model);
Format(tempString, sizeof(tempString), "%d %d %d %d", color[0], color[1], color[2], color[3]);
DispatchKeyValue(carEntity, "rendercolor", tempString);
Debug("spawning alarm car ent%d \"%s\" (m=%s) at %.0f %.0f %.0f", carEntity, carName, model, vPos[0], vPos[1], vPos[2]);
Format(tempString, sizeof(tempString), "%s,PlaySound,,0.2,-1", chirpSoundName);
DispatchKeyValue(carEntity, "OnCarAlarmChirpStart", tempString);
Format(tempString, sizeof(tempString), "%s,ShowSprite,,0.2,-1", lightsName);
DispatchKeyValue(carEntity, "OnCarAlarmChirpStart", tempString);
Format(tempString, sizeof(tempString), "%s,HideSprite,,0.7,-1", lightsName);
DispatchKeyValue(carEntity, "OnCarAlarmChirpEnd", tempString);
Format(tempString, sizeof(tempString), "%s,Enable,,0,-1", timerName);
DispatchKeyValue(carEntity, "OnCarAlarmStart", tempString);
Format(tempString, sizeof(tempString), "%s,PlaySound,,0,-1", alarmSoundName);
DispatchKeyValue(carEntity, "OnCarAlarmStart", tempString);
Format(tempString, sizeof(tempString), "%s,Enable,,0,-1", glassOffName);
DispatchKeyValue(carEntity, "OnCarAlarmStart", tempString);
DispatchKeyValue(carEntity, "OnHitByTank", tempString);
Format(tempString, sizeof(tempString), "%s,Kill,,0,-1", glassOnName);
DispatchKeyValue(carEntity, "OnCarAlarmStart", tempString);
DispatchKeyValue(carEntity, "OnHitByTank", tempString);
Format(tempString, sizeof(tempString), "%s,Kill,,0,-1", timerName);
DispatchKeyValue(carEntity, "OnCarAlarmEnd", tempString);
DispatchKeyValue(carEntity, "OnHitByTank", tempString);
Format(tempString, sizeof(tempString), "%s,Kill,,0,-1", alarmSoundName);
DispatchKeyValue(carEntity, "OnCarAlarmEnd", tempString);
DispatchKeyValue(carEntity, "OnHitByTank", tempString);
Format(tempString, sizeof(tempString), "%s,Kill,,0,-1", chirpSoundName);
DispatchKeyValue(carEntity, "OnCarAlarmEnd", tempString);
DispatchKeyValue(carEntity, "OnHitByTank", tempString);
Format(tempString, sizeof(tempString), "%s,Kill,,0,-1", lightsName);
DispatchKeyValue(carEntity, "OnCarAlarmEnd", tempString);
DispatchKeyValue(carEntity, "OnHitByTank", tempString);
Format(tempString, sizeof(tempString), "%s,Kill,,0,-1", headlightsName);
DispatchKeyValue(carEntity, "OnCarAlarmEnd", tempString);
DispatchKeyValue(carEntity, "OnHitByTank", tempString);
Format(tempString, sizeof(tempString), "%s,Kill,,0,-1", remarkName);
DispatchKeyValue(carEntity, "OnCarAlarmEnd", tempString);
DispatchKeyValue(carEntity, "OnHitByTank", tempString);
Format(tempString, sizeof(tempString), "%s,Kill,,0,-1", gameEventName);
DispatchKeyValue(carEntity, "OnCarAlarmEnd", tempString);
DispatchKeyValue(carEntity, "OnHitByTank", tempString);
DispatchKeyValueVector(carEntity, "origin", vPos);
DispatchKeyValueVector(carEntity, "angles", vAng);
DispatchSpawn(carEntity);
// create glasses
strcopy(tempString, sizeof(tempString), model);
ReplaceString(tempString, sizeof(tempString), ".mdl", "_glass.mdl");
if(PrecacheModel(tempString))
CreateGlass(tempString, glassOnName, false, vPos, vAng, carName);
// CreateGlass(glassOffName, true, vPos, vAng, carName);
CreateSound(alarmSoundName, "16", "Car.Alarm", vPos, carName);
CreateSound(chirpSoundName, "48", "Car.Alarm.Chirp2", vPos, carName);
CreateLights(lightsName, vPos, vAng, carName);
CreateHeadlights(headlightsName, vPos, vAng, carName);
CreateLogicTimer(timerName, lightsName, headlightsName, vPos, carName);
CreateRemark(remarkName, vPos, vAng, carName);
CreateGameEvent(gameEventName, vPos, vAng, carName);
return carEntity;
}
/****************************************************************************************************/
void CreateGlass(const char[] model, char[] targetName, bool startDisabled, float vPos[3], float vAng[3], char[] carName)
{
int entity = CreateEntityByName("prop_car_glass");
DispatchKeyValue(entity, "targetname", targetName);
DispatchKeyValue(entity, "model", model);
DispatchKeyValue(entity, "StartDisabled", startDisabled ? "1" : "0");
DispatchKeyValueVector(entity, "origin", vPos);
DispatchKeyValueVector(entity, "angles", vAng);
DispatchSpawn(entity);
SetVariantString(carName);
AcceptEntityInput(entity, "SetParent", entity, entity, 0);
}
/****************************************************************************************************/
void CreateSound(char[] targetName, char[] spawnFlags, char[] messageName, float vPos[3], char[] carName)
{
int entity = CreateEntityByName("ambient_generic");
float newPos[3];
newPos = vPos;
newPos[2] += 80.0;
DispatchKeyValue(entity, "targetname", targetName);
DispatchKeyValue(entity, "spawnflags", spawnFlags);
DispatchKeyValue(entity, "message", messageName);
DispatchKeyValue(entity, "SourceEntityName", carName);
DispatchKeyValue(entity, "radius", "4000");
DispatchKeyValueVector(entity, "origin", newPos);
DispatchSpawn(entity);
ActivateEntity(entity); // Don't work without it
SetVariantString(carName);
AcceptEntityInput(entity, "SetParent", entity, entity, 0);
}
/****************************************************************************************************/
void CreateLights(char[] lightsName, float vPos[3], float vAng[3], char[] carName)
{
float distance[6] = {DISTANCE_FRONT, DISTANCE_SIDETURN, DISTANCE_UPFRONT, DISTANCE_BACK, DISTANCE_SIDE, DISTANCE_UPBACK};
float newPos[3];
float lightDistance[3];
newPos = vPos;
lightDistance[0] = distance[0];
lightDistance[1] = distance[1]*-1.0;
lightDistance[2] = distance[2];
MoveVectorvPos3D(newPos, vAng, lightDistance); // front left
CreateLight(lightsName, COLOR_YELLOWLIGHT, newPos, carName);
newPos = vPos;
lightDistance[1] = distance[1];
MoveVectorvPos3D(newPos, vAng, lightDistance); // front right
CreateLight(lightsName, COLOR_YELLOWLIGHT, newPos, carName);
newPos = vPos;
lightDistance[0] = distance[3]*-1.0;
lightDistance[1] = distance[4]*-1.0;
lightDistance[2] = distance[5];
MoveVectorvPos3D(newPos, vAng, lightDistance); // back left
CreateLight(lightsName, COLOR_REDLIGHT, newPos, carName);
newPos = vPos;
lightDistance[1] = distance[4];
MoveVectorvPos3D(newPos, vAng, lightDistance); // back right
CreateLight(lightsName, COLOR_REDLIGHT, newPos, carName);
}
/****************************************************************************************************/
void CreateLight(char[] targetName, char[] renderColor, float vPos[3], char[] carName)
{
int entity = CreateEntityByName("env_sprite");
DispatchKeyValue(entity, "targetname", targetName);
DispatchKeyValue(entity, "rendercolor", renderColor);
DispatchKeyValue(entity, "model", ALARMCAR_GLOW_SPRITE);
DispatchKeyValue(entity, "scale", "0.5");
DispatchKeyValue(entity, "rendermode", "9");
DispatchKeyValue(entity, "renderamt", "255");
DispatchKeyValue(entity, "HDRColorScale", "0.7");
DispatchKeyValue(entity, "GlowProxySize", "5");
DispatchKeyValueVector(entity, "origin", vPos);
DispatchSpawn(entity);
SetVariantString(carName);
AcceptEntityInput(entity, "SetParent", entity, entity, 0);
}
/****************************************************************************************************/
void CreateHeadlights(char[] headlightsName, float vPos[3], float vAng[3], char[] carName)
{
float distance[3] = {DISTANCE_FRONT, DISTANCE_SIDE, DISTANCE_UPFRONT};
float newPos[3];
float headlightDistance[3];
newPos = vPos;
headlightDistance[0] = distance[0];
headlightDistance[1] = distance[1]*-1.0;
headlightDistance[2] = distance[2];
MoveVectorvPos3D(newPos, vAng, headlightDistance); // front left
CreateHeadlight(headlightsName, newPos, vAng, carName);
newPos = vPos;
headlightDistance[1] = distance[1];
MoveVectorvPos3D(newPos, vAng, headlightDistance); // front right
CreateHeadlight(headlightsName, newPos, vAng, carName);
}
/****************************************************************************************************/
void CreateHeadlight(char[] targetName, float vPos[3], float vAng[3], char[] carName)
{
int entity = CreateEntityByName("beam_spotlight");
DispatchKeyValue(entity, "targetname", targetName);
DispatchKeyValue(entity, "rendercolor", COLOR_WHITELIGHT);
DispatchKeyValue(entity, "spotlightwidth", "32");
DispatchKeyValue(entity, "spotlightlength", "256");
DispatchKeyValue(entity, "spawnflags", "2");
DispatchKeyValue(entity, "rendermode", "5");
DispatchKeyValue(entity, "renderamt", "150");
DispatchKeyValue(entity, "maxspeed", "100");
DispatchKeyValue(entity, "HDRColorScale", "0.5");
DispatchKeyValueVector(entity, "origin", vPos);
DispatchKeyValueVector(entity, "angles", vAng);
DispatchSpawn(entity);
SetVariantString(carName);
AcceptEntityInput(entity, "SetParent", entity, entity, 0);
}
/****************************************************************************************************/
void CreateLogicTimer(char[] targetName, char[] lightsName, char[] headlightsName, float vPos[3], char[] carName)
{
int entity = CreateEntityByName("logic_timer");
DispatchKeyValue(entity, "targetname", targetName);
DispatchKeyValue(entity, "StartDisabled", "1");
DispatchKeyValue(entity, "RefireTime", "0.75");
char tempString[128];
Format(tempString, sizeof(tempString), "%s,ShowSprite,,0,-1", lightsName);
DispatchKeyValue(entity, "OnTimer", tempString);
Format(tempString, sizeof(tempString), "%s,ShowSprite,,0,-1", lightsName);
DispatchKeyValue(entity, "OnTimer", tempString);
Format(tempString, sizeof(tempString), "%s,LightOn,,0,-1", headlightsName);
DispatchKeyValue(entity, "OnTimer", tempString);
Format(tempString, sizeof(tempString), "%s,HideSprite,,0.5,-1", lightsName);
DispatchKeyValue(entity, "OnTimer", tempString);
Format(tempString, sizeof(tempString), "%s,HideSprite,,0.5,-1", lightsName);
DispatchKeyValue(entity, "OnTimer", tempString);
Format(tempString, sizeof(tempString), "%s,LightOff,,0.5,-1", headlightsName);
DispatchKeyValue(entity, "OnTimer", tempString);
DispatchKeyValueVector(entity, "origin", vPos);
DispatchSpawn(entity);
SetVariantString(carName);
AcceptEntityInput(entity, "SetParent", entity, entity, 0);
}
/****************************************************************************************************/
void CreateRemark(char[] targetName, float vPos[3], float vAng[3], char[] carName)
{
int entity = CreateEntityByName("info_remarkable");
DispatchKeyValue(entity, "targetname", targetName);
DispatchKeyValue(entity, "contextsubject", "remark_caralarm");
DispatchKeyValueVector(entity, "origin", vPos);
DispatchKeyValueVector(entity, "angles", vAng);
DispatchSpawn(entity);
SetVariantString(carName);
AcceptEntityInput(entity, "SetParent", entity, entity, 0);
}
/****************************************************************************************************/
void CreateGameEvent(char[] targetName, float vPos[3], float vAng[3], char[] carName)
{
int entity = CreateEntityByName("info_game_event_proxy");
DispatchKeyValue(entity, "targetname", targetName);
DispatchKeyValue(entity, "spawnflags", "1");
DispatchKeyValue(entity, "range", "100");
DispatchKeyValue(entity, "event_name", "explain_disturbance");
DispatchKeyValueVector(entity, "origin", vPos);
DispatchKeyValueVector(entity, "angles", vAng);
DispatchSpawn(entity);
SetVariantString(carName);
AcceptEntityInput(entity, "SetParent", entity, entity, 0);
}
/****************************************************************************************************/
void MoveVectorvPos3D(float vPos[3], float constvAng[3], float constDistance[3])
{
float vAng[3], dirFw[3], dirRi[3], dirUp[3], distance[3];
distance = constDistance;
vAng[0] = DegToRad(constvAng[0]);
vAng[1] = DegToRad(constvAng[1]);
vAng[2] = DegToRad(constvAng[2]);
// roll (rotation over x)
dirFw[0] = 1.0;
dirFw[1] = 0.0;
dirFw[2] = 0.0;
dirRi[0] = 0.0;
dirRi[1] = Cosine(vAng[2]);
dirRi[2] = Sine(vAng[2])*-1;
dirUp[0] = 0.0;
dirUp[1] = Sine(vAng[2]);
dirUp[2] = Cosine(vAng[2]);
MatrixMulti(dirFw, dirRi, dirUp, distance);
// pitch (rotation over y)
dirFw[0] = Cosine(vAng[0]);
dirFw[1] = 0.0;
dirFw[2] = Sine(vAng[0]);
dirRi[0] = 0.0;
dirRi[1] = 1.0;
dirRi[2] = 0.0;
dirUp[0] = Sine(vAng[0])*-1;
dirUp[1] = 0.0;
dirUp[2] = Cosine(vAng[0]);
MatrixMulti(dirFw, dirRi, dirUp, distance);
// yaw (rotation over z)
dirFw[0] = Cosine(vAng[1]);
dirFw[1] = Sine(vAng[1])*-1;
dirFw[2] = 0.0;
dirRi[0] = Sine(vAng[1]);
dirRi[1] = Cosine(vAng[1]);
dirRi[2] = 0.0;
dirUp[0] = 0.0;
dirUp[1] = 0.0;
dirUp[2] = 1.0;
MatrixMulti(dirFw, dirRi, dirUp, distance);
// addition
for (int i = 0; i < 3; i++) vPos[i] += distance[i];
}
/****************************************************************************************************/
void MatrixMulti(float matA[3], float matB[3], float matC[3], float vec[3])
{
float res[3];
for (int i = 0; i < 3; i++) res[0] += matA[i]*vec[i];
for (int i = 0; i < 3; i++) res[1] += matB[i]*vec[i];
for (int i = 0; i < 3; i++) res[2] += matC[i]*vec[i];
vec = res;
}
/**
// ====================================================================================================
:::END::: -> Source Code from DieTeetasse - [L4D1&2] Spawn Alarmcars plugin https://forums.alliedmods.net/showthread.php?t=139352
// ====================================================================================================
*/

View file

@ -35,8 +35,8 @@ void OpenVariantsMenu(int client) {
Menu menu = new Menu(BuilderHandler_VariantsMenu);
menu.SetTitle("%s > Variants", g_builder.selectedSceneId);
char id[8], display[32];
menu.AddItem("new", "New");
menu.AddItem("-1", "None (Shared Scene)");
menu.AddItem("new", "New Variant");
menu.AddItem("-1", "Global Scene Variant");
JSONArray variants = view_as<JSONArray>(g_builder.selectedSceneData.Get("variants"));
JSONObject varObj;
@ -45,9 +45,9 @@ void OpenVariantsMenu(int client) {
varObj = view_as<JSONObject>(variants.Get(i));
entities = view_as<JSONArray>(varObj.Get("entities"));
if(i == g_builder.selectedVariantIndex) {
Format(display, sizeof(display), "%d entities (selected)", entities.Length);
Format(display, sizeof(display), "#%d - %d entities (✔)", i, entities.Length);
} else {
Format(display, sizeof(display), "%d entities", entities.Length);
Format(display, sizeof(display), "#%d - %d entities", i, entities.Length);
}
IntToString(i, id, sizeof(id));
menu.AddItem(id, display);

View file

@ -24,6 +24,8 @@ TopMenu g_topMenu;
char g_currentMap[64];
ConVar enabledBlacklist;
//int g_markedMode
#include <editor/editor.sp>
@ -80,6 +82,8 @@ public void OnPluginStart() {
LoadTranslations("common.phrases");
HookEvent("player_spawn", Event_PlayerSpawn);
enabledBlacklist = CreateConVar("editor_denylist", "7", "The lists to check, add bits together.\n1 = classnames\n2 = models\n4 = targetnames", FCVAR_NONE, true, 0.0);
RegAdminCmd("sm_mkwall", Command_MakeWall, ADMFLAG_CUSTOM2);
RegAdminCmd("sm_edit", Command_Editor, ADMFLAG_CUSTOM2);
RegAdminCmd("sm_wall", Command_Editor, ADMFLAG_CUSTOM2);
@ -489,13 +493,15 @@ char FORBIDDEN_MODELS[MAX_FORBIDDEN_MODELS][] = {
bool CheckBlacklist(int entity) {
if(entity == 0) return false;
static char buffer[64];
GetEntityClassname(entity, buffer, sizeof(buffer));
for(int i = 0; i < MAX_FORBIDDEN_CLASSNAMES; i++) {
if(StrEqual(FORBIDDEN_CLASSNAMES[i], buffer)) {
return false;
if(enabledBlacklist.IntValue & 1) {
GetEntityClassname(entity, buffer, sizeof(buffer));
for(int i = 0; i < MAX_FORBIDDEN_CLASSNAMES; i++) {
if(StrEqual(FORBIDDEN_CLASSNAMES[i], buffer)) {
return false;
}
}
}
if(StrContains(buffer, "prop_") > -1) {
if(enabledBlacklist.IntValue & 2) {
GetEntPropString(entity, Prop_Data, "m_ModelName", buffer, sizeof(buffer));
for(int i = 0; i < MAX_FORBIDDEN_MODELS; i++) {
if(StrEqual(FORBIDDEN_MODELS[i], buffer)) {
@ -503,9 +509,11 @@ bool CheckBlacklist(int entity) {
}
}
}
GetEntPropString(entity, Prop_Data, "m_iName", buffer, sizeof(buffer));
if(StrEqual(buffer, "l4d2_randomizer")) {
return false;
if(enabledBlacklist.IntValue & 4) {
GetEntPropString(entity, Prop_Data, "m_iName", buffer, sizeof(buffer));
if(StrContains(buffer, "randomizer") > -1) {
return false;
}
}
return true;
}

View file

@ -22,9 +22,9 @@ int g_iLaserIndex;
#if defined DEBUG_BLOCKERS
#include <smlib/effects>
#endif
#define ENT_PROP_NAME "l4d2_randomizer"
#define ENT_ENV_NAME "l4d2_randomizer"
#define ENT_BLOCKER_NAME "l4d2_randomizer"
#define ENT_PROP_NAME "randomizer"
#define ENT_ENV_NAME "randomizer"
#define ENT_BLOCKER_NAME "randomizer"
#include <gamemodes/ents>
#define MAX_SCENE_NAME_LENGTH 32
@ -100,6 +100,7 @@ enum struct BuilderData {
}
#include <randomizer/rbuild.sp>
#include <randomizer/caralarm.sp>
public Plugin myinfo =
{
@ -116,24 +117,40 @@ public void OnPluginStart() {
SetFailState("This plugin is for L4D/L4D2 only.");
}
HookEvent("round_start_post_nav", Event_RoundStartPosNav);
RegAdminCmd("sm_rcycle", Command_CycleRandom, ADMFLAG_CHEATS);
RegAdminCmd("sm_expent", Command_ExportEnt, ADMFLAG_GENERIC);
RegAdminCmd("sm_rbuild", Command_RandomizerBuild, ADMFLAG_CHEATS);
cvarEnabled = CreateConVar("sm_randomizer_enabled", "0");
HookEvent("player_first_spawn", Event_PlayerFirstSpawn);
g_MapData.activeScenes = new ArrayList(sizeof(ActiveSceneData));
}
void Event_PlayerFirstSpawn(Event event, const char[] name ,bool dontBroadcast) {
int client = GetClientOfUserId(event.GetInt("userid"));
if(GetUserFlagBits(client) & ADMFLAG_CHAT) {
// If enabled but no map loaded:
if(cvarEnabled.BoolValue && g_MapData.scenes == null)
PrintToChat(client, "Randomizer Note: This map has no randomizer support at the moment.");
}
}
void Event_RoundStartPosNav(Event event, const char[] name ,bool dontBroadcast) {
if(cvarEnabled.BoolValue)
CreateTimer(5.0, Timer_Run);
}
// TODO: on round start
public void OnMapStart() {
g_iLaserIndex = PrecacheModel("materials/sprites/laserbeam.vmt", true);
GetCurrentMap(currentMap, sizeof(currentMap));
if(cvarEnabled.BoolValue)
CreateTimer(5.0, Timer_Run);
}
public void OnMapEnd() {
g_builder.Cleanup();
Cleanup();
@ -196,7 +213,7 @@ public Action Command_CycleRandom(int client, int args) {
if(client > 0)
PrintCenterText(client, "Cycled flags=%d", flags);
} else {
ReplyToCommand(client, "Active Scenes:");
ReplyToCommand(client, "Active Scenes (%d/%d):", g_MapData.activeScenes.Length, g_MapData.scenes.Length);
ActiveSceneData scene;
for(int i = 0; i < g_MapData.activeScenes.Length; i++) {
g_MapData.activeScenes.GetArray(i, scene);
@ -284,7 +301,7 @@ Action Command_RandomizerBuild(int client, int args) {
} else if(StrEqual(arg, "menu")) {
OpenMainMenu(client);
} else if(g_builder.mapData == null) {
ReplyToCommand(client, "No map data for %s, either load with /rbuild load, or start new /rbuild new", currentMap);
ReplyToCommand(client, "No map data loaded for %s, either load with /rbuild load, or start new /rbuild new", currentMap);
return Plugin_Handled;
} else if(StrEqual(arg, "save")) {
SaveMapJson(currentMap, g_builder.mapData);
@ -358,10 +375,10 @@ JSONObject ExportEntity(int entity, ExportType exportType = Export_Model) {
GetEntPropVector(entity, Prop_Send, "m_angRotation", angles);
GetEntPropVector(entity, Prop_Send, "m_vecMaxs", size);
char model[128];
char classname[128], model[128];
JSONObject entityData = new JSONObject();
GetEntityClassname(entity, model, sizeof(model));
if(StrContains(model, "prop_") == -1) {
GetEntityClassname(entity, classname, sizeof(classname));
if(StrContains(classname, "prop_") == -1) {
entityData.Set("scale", VecToArray(size));
}
if(exportType == Export_HammerId) {
@ -376,6 +393,7 @@ JSONObject ExportEntity(int entity, ExportType exportType = Export_Model) {
entityData.SetString("model", model);
} else {
GetEntPropString(entity, Prop_Data, "m_ModelName", model, sizeof(model));
entityData.SetString("type", classname);
entityData.SetString("model", model);
}
entityData.Set("origin", VecToArray(origin));
@ -567,17 +585,18 @@ enum InputType {
enum struct VariantInputData {
char name[MAX_INPUTS_CLASSNAME_LENGTH];
InputType type;
char input[32];
char input[64];
void Trigger() {
int entity = -1;
switch(this.type) {
case Input_Classname: {
entity = FindEntityByClassname(entity, this.name);
this._trigger(entity);
while((entity = FindEntityByClassname(entity, this.name)) != INVALID_ENT_REFERENCE) {
this._trigger(entity);
}
}
case Input_Targetname: {
char targetname[32];
char targetname[64];
while((entity = FindEntityByClassname(entity, "*")) != INVALID_ENT_REFERENCE) {
GetEntPropString(entity, Prop_Data, "m_iName", targetname, sizeof(targetname));
if(StrEqual(targetname, this.name)) {
@ -613,14 +632,19 @@ enum struct VariantInputData {
AcceptEntityInput(entity, "Close");
AcceptEntityInput(entity, "Lock");
AcceptEntityInput(entity, "SetUnbreakable");
}else {
} else {
char cmd[32];
// Split input "a b" to a with variant "b"
int len = SplitString(this.input, " ", cmd, sizeof(cmd));
if(len > -1) SetVariantString(this.input[len]);
if(len > -1) {
SetVariantString(this.input[len]);
AcceptEntityInput(entity, cmd);
Debug("_trigger(%d): %s (v=%s)", entity, cmd, this.input[len]);
} else {
Debug("_trigger(%d): %s", entity, this.input);
AcceptEntityInput(entity, this.input);
}
Debug("_trigger(%d): %s (v=%s)", entity, this.input, cmd);
AcceptEntityInput(entity, this.input);
}
}
}
@ -858,7 +882,7 @@ void loadChoice(SceneData scene, JSONObject choiceData, JSONArray extraEntities)
// Parses entities and loads to choice.entities
loadChoiceEntity(choice.entities, view_as<JSONObject>(extraEntities.Get(i)));
}
delete extraEntities;
// delete extraEntities;
}
// Load all inputs
if(choiceData.HasKey("inputs")) {
@ -874,6 +898,7 @@ void loadChoice(SceneData scene, JSONObject choiceData, JSONArray extraEntities)
for(int i = 0; i < scenes.Length; i++) {
scenes.GetString(i, sceneId, sizeof(sceneId));
choice.forcedScenes.PushString(sceneId);
Debug("scene %s: require %s", scene.name, sceneId);
}
delete scenes;
}
@ -882,6 +907,7 @@ void loadChoice(SceneData scene, JSONObject choiceData, JSONArray extraEntities)
void loadChoiceInput(ArrayList list, JSONObject inputData) {
VariantInputData input;
input.type = Input_Classname;
// Check classname -> targetname -> hammerid
if(!inputData.GetString("classname", input.name, sizeof(input.name))) {
if(inputData.GetString("targetname", input.name, sizeof(input.name))) {
@ -936,10 +962,10 @@ void loadChoiceEntity(ArrayList list, JSONObject entityData) {
entityData.GetString("model", entity.model, sizeof(entity.model));
if(!entityData.GetString("type", entity.type, sizeof(entity.type))) {
entity.type = "prop_dynamic";
} else if(entity.type[0] == '_') {
} /*else if(entity.type[0] == '_') {
LogError("Invalid custom entity type \"%s\"", entity.type);
return;
}
}*/
GetVector(entityData, "origin", entity.origin);
GetVector(entityData, "angles", entity.angles);
GetVector(entityData, "scale", entity.scale);
@ -1013,24 +1039,35 @@ void selectScenes(int flags = 0) {
// Traverse active scenes, loading any other scene it requires (via .force_scenes)
ActiveSceneData aScene;
SceneVariantData choice;
char sceneId[64];
// list of scenes that will need to be forced if not already:
ArrayList forcedScenes = new ArrayList(ByteCountToCells(MAX_SCENE_NAME_LENGTH));
for(int i = 0; i < g_MapData.activeScenes.Length; i++) {
g_MapData.activeScenes.GetArray(i, aScene);
g_MapData.scenes.GetArray(i, scene);
scene.variants.GetArray(aScene.variantIndex, choice);
if(choice.forcedScenes != null) {
for(int j = 0; j < choice.forcedScenes.Length; j++) {
choice.forcedScenes.GetString(j, key, sizeof(key));
forcedScenes.PushString(key);
// Load scene from active scene entry
if(!g_MapData.scenesKv.GetArray(aScene.name, scene, sizeof(scene))) {
// can't find scene, ignore
continue;
}
if(aScene.variantIndex < scene.variants.Length) {
scene.variants.GetArray(aScene.variantIndex, choice);
if(choice.forcedScenes != null) {
for(int j = 0; j < choice.forcedScenes.Length; j++) {
choice.forcedScenes.GetString(j, key, sizeof(key));
forcedScenes.PushString(key);
}
}
}
}
if(forcedScenes.Length > 0) {
Debug("Loading %d forced scenes", forcedScenes.Length);
}
// Iterate and activate any forced scenes
for(int i = 0; i < forcedScenes.Length; i++) {
forcedScenes.GetString(i, key, sizeof(key));
// Check if scene was already loaded
bool isSceneAlreadyLoaded = false;
for(int j = 0; j < g_MapData.activeScenes.Length; i++) {
for(int j = 0; j < g_MapData.activeScenes.Length; j++) {
g_MapData.activeScenes.GetArray(j, aScene);
if(StrEqual(aScene.name, key)) {
isSceneAlreadyLoaded = true;
@ -1077,7 +1114,6 @@ void selectScene(SceneData scene, int flags) {
}
}
}
Debug("Total choices: %d", choices.Length);
if(flags & view_as<int>(FLAG_ALL_VARIANTS)) {
delete choices;
} else if(choices.Length > 0) {
@ -1118,7 +1154,7 @@ void spawnEntity(VariantEntityData entity) {
CreateEnvBlockerScaled(entity.type, entity.origin, entity.scale);
} else if(StrEqual(entity.type, "infodecal")) {
CreateDecal(entity.model, entity.origin);
} else if(StrContains(entity.type, "prop_") == 0) {
} else if(StrContains(entity.type, "prop_") == 0 || StrEqual(entity.type, "prop_fuel_barrel")) {
if(entity.model[0] == '\0') {
LogError("Missing model for entity with type \"%s\"", entity.type);
return;
@ -1165,6 +1201,8 @@ void spawnEntity(VariantEntityData entity) {
}
if(!found)
Debug("Warn: Could not find entity (classname=%s)", entity.model);
} else if(StrContains(entity.type, "_car") != -1) {
SpawnCar(entity);
} else {
LogError("Unknown entity type \"%s\"", entity.type);
}
@ -1201,6 +1239,17 @@ void Cleanup() {
}
delete g_MapData.lumpEdits;
// Cleanup all alarm car entities:
int entity = -1;
char targetname[128];
while((entity = FindEntityByClassname(entity, "*")) != INVALID_ENT_REFERENCE) {
GetEntPropString(entity, Prop_Data, "m_iName", targetname, sizeof(targetname));
if(StrContains(targetname, "randomizer_car") != -1) {
RemoveEntity(entity);
}
}
// TODO: delete car alarms
DeleteCustomEnts();
g_MapData.activeScenes.Clear();
}