Update scripts / binaries

This commit is contained in:
Jackzie 2024-10-06 23:17:21 -05:00
parent b42d0ecb46
commit 807dbfd805
16 changed files with 196 additions and 30 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1102,7 +1102,7 @@ void AddPlayerRecord(int client, ClientState state) {
StartRecord(Live_Player);
sendBuffer.WriteInt(GetClientUserId(client));
sendBuffer.WriteString(steamidCache[client]);
sendBuffer.WriteByte(state);
sendBuffer.WriteByte(view_as<int>(state));
sendBuffer.WriteInt(state == Client_Disconnected ? GetTime() : playerJoinTime[client]);
sendBuffer.WriteString(nameCache[client]);
EndRecord();

23
scripting/include/.gitignore vendored Normal file
View file

@ -0,0 +1,23 @@
*.*
!.gitignore
!epi/**
!feedthetrolls/**
!gamemodes/**
!guesswho/**
!hats/**
!hideandseek/**
!randomizer/**
!editor/**
!editor/**
!ftt.inc
!hats_editor.inc
!jutils.inc
!l4d_anti_rush.inc
!l4d2_perms.inc
!l4d2_detections.inc
!l4d_survivor_identity_fix.inc
!l4d2_usermsg.inc
!overlay.inc
!player_notes.inc
!tkstopper.inc
!anymap.inc

View file

@ -444,6 +444,7 @@ int SpawnCategoryHandler(Menu menu, MenuAction action, int client, int param2) {
ShowSpawnRoot(client);
}
} else {
PrintToServer("SpawnCategoryHandler: calling ClearItemBuffer, Menu cancelled");
g_PropData[client].CleanupBuffers();
}
} else if (action == MenuAction_End)
@ -470,7 +471,6 @@ int SpawnItemHandler(Menu menu, MenuAction action, int client, int param2) {
// Use same item menu again:
ShowItemMenu(client);
} else if(action == MenuAction_Cancel) {
g_PropData[client].ClearItemBuffer();
if(param2 == MenuCancel_ExitBack) {
CategoryData category;
if(g_PropData[client].PopCategory(category)) {
@ -480,7 +480,8 @@ int SpawnItemHandler(Menu menu, MenuAction action, int client, int param2) {
// If there is no categories, it means we are in a temp menu (search / recents / favorites)
ShowSpawnRoot(client);
}
} else {
} else if(param2 != MenuCancel_Interrupted) {
PrintToServer("SpawnItemHandler: calling ClearItemBuffer, Menu cancelled. param2=%d", param2);
g_PropData[client].CleanupBuffers();
}
} else if (action == MenuAction_End) {

View file

@ -426,6 +426,9 @@ ArrayList SearchItems(const char[] query) {
ArrayList items = new ArrayList(sizeof(ItemData));
ItemData item;
SearchData data;
if(results.Length > MAX_SEARCH_RESULTS) {
results.Resize(MAX_SEARCH_RESULTS);
}
for(int i = 0; i < results.Length; i++) {
results.GetArray(i, data);
item.FromSearchData(data);
@ -471,7 +474,6 @@ bool _searchItems(ArrayList results, ArrayList items, const char[] query) {
search.FromItemData(item);
search.index = searchIndex;
results.PushArray(search);
if(results.Length > MAX_SEARCH_RESULTS) return false;
}
}
return true;

View file

@ -5,8 +5,8 @@
#define DIRECTOR_WITCH_CHECK_TIME 30.0 // How often to check if a witch should be spawned
#define DIRECTOR_WITCH_MAX_WITCHES 5 // The maximum amount of extra witches to spawn
#define DIRECTOR_WITCH_ROLLS 3 // The number of dice rolls, increase if you want to increase freq
#define DIRECTOR_MIN_SPAWN_TIME 13.0 // Possibly randomized, per-special
#define DIRECTOR_SPAWN_CHANCE 0.038 // The raw chance of a spawn
#define DIRECTOR_MIN_SPAWN_TIME 13.0 // Possibly randomized, per-special, in seconds
ConVar directorSpawnChance; // Base chance of a special spawning, changed by player stress
#define DIRECTOR_CHANGE_LIMIT_CHANCE 0.05 // The chance that the maximum amount per-special is changed
#define DIRECTOR_SPECIAL_TANK_CHANCE 0.05 // The chance that specials can spawn when a tank is active
#define DIRECTOR_STRESS_CUTOFF 0.75 // The minimum chance a random cut off stress value is chosen [this, 1.0]
@ -41,7 +41,8 @@ enum specialType {
enum directorState {
DState_Normal,
DState_NoPlayersOrNotCoop,
DState_PendingMinFlowOrDisabled,
DState_PendingMinFlow,
DState_Disabled,
DState_MaxSpecialTime,
DState_PlayerChance,
DState_Resting,
@ -49,10 +50,11 @@ enum directorState {
DState_HighStress,
DState_MaxDirectorSpecials,
}
char DIRECTOR_STATE[9][] = {
char DIRECTOR_STATE[10][] = {
"normal",
"no players / not coop",
"pending minflow OR disabled",
"pending minflow",
"disabled",
"max special in window",
"player scaled chance",
"rest period",
@ -388,7 +390,8 @@ directorState Director_Think() {
// C. Special spawning is enabled
gd_maxSpecials = L4D2_GetScriptValueInt("MaxSpecials", 0);
if(gd_maxSpecials <= 0) return DState_MaxDirectorSpecials;
if( ~cvEPISpecialSpawning.IntValue & 1 || !L4D_HasAnySurvivorLeftSafeArea() || g_highestFlowAchieved < g_minFlowSpawn) return DState_PendingMinFlowOrDisabled;
if(~cvEPISpecialSpawning.IntValue & 1 ) return DState_Disabled;
if(!L4D_HasAnySurvivorLeftSafeArea() || g_highestFlowAchieved < g_minFlowSpawn) return DState_PendingMinFlow;
// Check if a rest period is given
if(Director_ShouldRest()) {
@ -423,7 +426,7 @@ directorState Director_Think() {
return DState_HighStress;
}
// Scale the chance where stress = 0.0, the chance is 50% more, and stress = 1.0, the chance is 50% less
float spawnChance = DIRECTOR_SPAWN_CHANCE + ((0.5 - curAvgStress) / 10.0);
float spawnChance = directorSpawnChance.FloatValue + ((0.5 - curAvgStress) / 10.0);
for(int i = 0; i < NUM_SPECIALS; i++) {
specialType special = view_as<specialType>(i);
// Skip if we hit our limit, or too soon:

View file

@ -173,6 +173,7 @@ stock int StartPropCreate(const char[] entClass, const char[] model, const float
stock int CreateProp(const char[] entClass, const char[] model, const float pos[3], const float ang[3] = NULL_VECTOR, const float vel[3] = NULL_VECTOR) {
int entity = StartPropCreate(entClass, model, pos, ang, vel);
if(entity == -1) return -1;
if(DispatchSpawn(entity)) {
#if defined DEBUG_LOG_MAPSTART
PrintToServer("spawn prop %.1f %.1f %.1f model %s", pos[0], pos[1], pos[2], model[7]);
@ -281,17 +282,24 @@ stock int CreateParticle(const char[] sParticle, const float vPos[3], const floa
return 0;
}
stock void CreateDecal(const char[] texture, const float vPos[3]) {
int index = PrecacheDecal("decals/checkpointarrow01_black.vmt");
stock void CreateDecal(const char[] texture, const float origin[3]) {
int index = PrecacheDecal(texture);
if(index <= 0) {
LogError("CreateDecal: bad decal \"%s\", precache failed.", texture);
return;
}
PrintToServer("CreateDecal: %s -> %d", texture, index);
TE_Start("World Decal");
TE_WriteVector("m_vecOrigin", vPos);
TE_WriteVector("m_vecOrigin", origin);
// TE_WriteNum("m_nEntity", -1);
TE_WriteNum("m_nIndex", index);
TE_SendToAll();
TE_Start("BSP Decal");
TE_WriteVector("m_vecOrigin", vPos);
TE_WriteNum("m_nIndex", index);
TE_SendToAll();
// TE_Start("World Decal");
// TE_WriteVector("m_vecOrigin", origin);
// TE_WriteNum("m_nIndex", index);
// TE_SendToAll();
// int entity = CreateEntityByName("infodecal");
// if( entity != -1 ) {
// DispatchKeyValue(entity, "texture", "decals/checkpointarrow01_black.vmt");
@ -299,6 +307,7 @@ stock void CreateDecal(const char[] texture, const float vPos[3]) {
// TeleportEntity(entity, vPos, NULL_VECTOR, NULL_VECTOR);
// DispatchSpawn(entity);
// ActivateEntity(entity);
// AcceptEntityInput(entity, "Activate");
// }
}

View file

@ -12,7 +12,7 @@ int SpawnCar(VariantEntityData entity) {
}
char glassModel[64];
strcopy(glassModel, sizeof(glassModel), entity.type);
strcopy(glassModel, sizeof(glassModel), entity.model);
ReplaceString(glassModel, sizeof(glassModel), ".mdl", "_glass.mdl");
if(StrEqual(entity.type, "_car_physics")) {
vehicle = CreateProp("prop_physics", entity.model, entity.origin, entity.angles);
@ -20,10 +20,12 @@ int SpawnCar(VariantEntityData entity) {
vehicle = CreateProp("prop_dynamic", entity.model, entity.origin, entity.angles);
}
if(PrecacheModel(glassModel)) {
int glass = CreateProp(glassModel, entity.model, entity.origin, entity.angles);
int glass = CreateProp("prop_dynamic", glassModel, entity.origin, entity.angles);
if(glass != -1) {
SetVariantString("!activator");
AcceptEntityInput(glass, "SetParent", vehicle);
}
}
SetEntityRenderColor(vehicle, GetRandomInt(0, 255), GetRandomInt(0, 255), GetRandomInt(0, 255));
return vehicle;
}

View file

@ -43,7 +43,7 @@ void OpenVariantsMenu(int client) {
JSONArray entities;
for(int i = 0; i < variants.Length; i++) {
varObj = view_as<JSONObject>(variants.Get(i));
entities = view_as<JSONArray>(varObj.Get("entities"));
entities = varObj.HasKey("entities") ? view_as<JSONArray>(varObj.Get("entities")) : new JSONArray();
if(i == g_builder.selectedVariantIndex) {
Format(display, sizeof(display), "#%d - %d entities (✔)", i, entities.Length);
} else {

View file

@ -325,6 +325,7 @@ public void OnPluginStart() {
cvEPICommonCountScale = CreateConVar("epi_commons_scale_multiplier", "0", "This value is multiplied by the number of extra players playing. It's then added to z_common_limit. 5 players with value 5 would be z_common_limit + ", FCVAR_NONE, true, 0.0);
cvEPICommonCountScaleMax = CreateConVar("epi_commons_scale_max", "60", "The maximum amount that z_common_limit can be scaled to.", FCVAR_NONE, true, 0.0);
cvZCommonLimit = FindConVar("z_common_limit");
directorSpawnChance = CreateConVar("epi_director_special_chance", "0.038", "The base chance a special spawns, scaled by the survivor's average stress.", FCVAR_NONE, true, 0.0, true, 1.0);
cvEPICommonCountScale.AddChangeHook(Cvar_CommonScaleChange);
cvEPICommonCountScaleMax.AddChangeHook(Cvar_CommonScaleChange);

View file

@ -39,6 +39,7 @@ enum struct ActiveSceneData {
MapData g_MapData;
BuilderData g_builder;
char currentMap[64];
static int _ropeIndex;
enum struct BuilderData {
JSONObject mapData;
@ -84,6 +85,11 @@ enum struct BuilderData {
}
void AddEntity(int entity, ExportType exportType = Export_Model) {
JSONObject entityData = ExportEntity(entity, Export_Model);
this.AddEntityData(entityData);
}
void AddEntityData(JSONObject entityData) {
JSONArray entities;
if(g_builder.selectedVariantData == null) {
// Create <scene>.entities if doesn't exist:
@ -94,7 +100,6 @@ enum struct BuilderData {
} else {
entities = view_as<JSONArray>(g_builder.selectedVariantData.Get("entities"));
}
JSONObject entityData = ExportEntity(entity, Export_Model);
entities.Push(entityData);
}
}
@ -117,7 +122,7 @@ public void OnPluginStart() {
SetFailState("This plugin is for L4D/L4D2 only.");
}
HookEvent("round_start_post_nav", Event_RoundStartPosNav);
HookEvent("round_start_post_nav", Event_RoundStartPostNav);
RegAdminCmd("sm_rcycle", Command_CycleRandom, ADMFLAG_CHEATS);
RegAdminCmd("sm_expent", Command_ExportEnt, ADMFLAG_GENERIC);
@ -130,7 +135,13 @@ public void OnPluginStart() {
g_MapData.activeScenes = new ArrayList(sizeof(ActiveSceneData));
}
bool randomizerRan = false;
void Event_PlayerFirstSpawn(Event event, const char[] name ,bool dontBroadcast) {
if(!randomizerRan) {
CreateTimer(0.1, Timer_Run);
randomizerRan = true;
}
int client = GetClientOfUserId(event.GetInt("userid"));
if(GetUserFlagBits(client) & ADMFLAG_CHAT) {
// If enabled but no map loaded:
@ -139,9 +150,9 @@ void Event_PlayerFirstSpawn(Event event, const char[] name ,bool dontBroadcast)
}
}
void Event_RoundStartPosNav(Event event, const char[] name ,bool dontBroadcast) {
if(cvarEnabled.BoolValue)
CreateTimer(5.0, Timer_Run);
void Event_RoundStartPostNav(Event event, const char[] name ,bool dontBroadcast) {
// if(cvarEnabled.BoolValue)
// CreateTimer(15.0, Timer_Run);
}
// TODO: on round start
@ -152,6 +163,7 @@ public void OnMapStart() {
public void OnMapEnd() {
randomizerRan = false;
g_builder.Cleanup();
Cleanup();
}
@ -344,6 +356,10 @@ Action Command_RandomizerBuild(int client, int args) {
ReplyToCommand(client, "No entity found");
}
} else if(StrEqual(arg, "entityid")) {
if(g_builder.selectedVariantData == null) {
ReplyToCommand(client, "Please load map data, select a scene and a variant.");
return Plugin_Handled;
}
char arg1[32];
int entity = GetCmdArgInt(2);
GetCmdArg(3, arg1, sizeof(arg));
@ -359,6 +375,20 @@ Action Command_RandomizerBuild(int client, int args) {
} else {
ReplyToCommand(client, "No entity found");
}
} else if(StrEqual(arg, "decal")) {
if(g_builder.selectedVariantData == null) {
ReplyToCommand(client, "Please load map data, select a scene and a variant.");
return Plugin_Handled;
}
float pos[3];
GetLookingPosition(client, Filter_IgnorePlayer, pos);
Effect_DrawBeamBoxRotatableToAll(pos, { -5.0, -5.0, -5.0}, { 5.0, 5.0, 5.0}, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 40.0, 0.1, 0.1, 0, 0.0, {73, 0, 130, 255}, 0);
JSONObject obj = new JSONObject();
obj.SetString("type", "infodecal");
obj.Set("origin", VecToArray(pos));
obj.SetString("model", "decals/checkpointarrow01_black.vmt");
g_builder.AddEntityData(obj);
ReplyToCommand(client, "Added sprite to variant #%d", g_builder.selectedVariantIndex);
} else {
ReplyToCommand(client, "Unknown arg. Try: new, load, save, scenes, cursor");
}
@ -604,10 +634,13 @@ enum struct SceneVariantData {
enum struct VariantEntityData {
char type[32];
char model[128];
char targetname[128];
float origin[3];
float angles[3];
float scale[3];
int color[4];
ArrayList keyframes;
}
enum InputType {
@ -630,22 +663,32 @@ enum struct VariantInputData {
}
case Input_Targetname: {
char targetname[64];
int count = 0;
while((entity = FindEntityByClassname(entity, "*")) != INVALID_ENT_REFERENCE) {
GetEntPropString(entity, Prop_Data, "m_iName", targetname, sizeof(targetname));
if(StrEqual(targetname, this.name)) {
this._trigger(entity);
count++;
}
}
if(count == 0) {
PrintToServer("[Randomizer::WARN] Input TargetName=\"%s\" matched 0 entties", this.name);
}
}
case Input_HammerId: {
int targetId = StringToInt(this.name);
int count = 0;
while((entity = FindEntityByClassname(entity, "*")) != INVALID_ENT_REFERENCE) {
int hammerId = GetEntProp(entity, Prop_Data, "m_iHammerID");
if(hammerId == targetId ) {
this._trigger(entity);
count++;
break;
}
}
if(count == 0) {
PrintToServer("[Randomizer::WARN] Input HammerId=%d matched 0 entties", targetId);
}
}
}
}
@ -859,6 +902,8 @@ public bool RunMap(const char[] map, int flags) {
selectScenes(flags);
profiler.Stop();
_ropeIndex = 0;
Log("Done processing in %.4f seconds", g_MapData.scenes.Length, profiler.Time);
return true;
}
@ -993,12 +1038,32 @@ void loadLumpData(ArrayList list, JSONObject inputData) {
void loadChoiceEntity(ArrayList list, JSONObject entityData) {
VariantEntityData entity;
entityData.GetString("model", entity.model, sizeof(entity.model));
if(entityData.GetString("targetname", entity.targetname, sizeof(entity.targetname))) {
Format(entity.targetname, sizeof(entity.targetname), "randomizer_%s", entity.targetname);
}
if(!entityData.GetString("type", entity.type, sizeof(entity.type))) {
entity.type = "prop_dynamic";
} /*else if(entity.type[0] == '_') {
LogError("Invalid custom entity type \"%s\"", entity.type);
return;
}*/
if(StrEqual(entity.type, "move_rope")) {
if(!entityData.HasKey("keyframes")) {
LogError("move_rope entity is missing keyframes: Vec[] property");
return;
}
entity.keyframes = new ArrayList(3);
JSONArray keyframesData = view_as<JSONArray>(entityData.Get("keyframes"));
float vec[3];
for(int i = 0 ; i < keyframesData.Length; i++) {
JSONArray vecArray = view_as<JSONArray>(keyframesData.Get(i));
vec[0] = vecArray.GetFloat(0);
vec[1] = vecArray.GetFloat(1);
vec[2] = vecArray.GetFloat(2);
entity.keyframes.PushArray(vec);
}
}
GetVector(entityData, "origin", entity.origin);
GetVector(entityData, "angles", entity.angles);
GetVector(entityData, "scale", entity.scale);
@ -1206,13 +1271,16 @@ void spawnEntity(VariantEntityData entity) {
} else if(StrEqual(entity.type, "env_physics_blocker") || StrEqual(entity.type, "env_player_blocker")) {
CreateEnvBlockerScaled(entity.type, entity.origin, entity.scale);
} else if(StrEqual(entity.type, "infodecal")) {
Effect_DrawBeamBoxRotatableToAll(entity.origin, { -1.0, -5.0, -5.0}, { 1.0, 5.0, 5.0}, NULL_VECTOR, g_iLaserIndex, 0, 0, 0, 40.0, 0.1, 0.1, 0, 0.0, {73, 0, 130, 255}, 0);
CreateDecal(entity.model, entity.origin);
} 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;
} else if(!PrecacheModel(entity.model)) {
LogError("Precache of entity model \"%s\" with type \"%s\" failed", entity.model, entity.type);
return;
}
PrecacheModel(entity.model);
int prop = CreateProp(entity.type, entity.model, entity.origin, entity.angles);
SetEntityRenderColor(prop, entity.color[0], entity.color[1], entity.color[2], entity.color[3]);
} else if(StrEqual(entity.type, "hammerid")) {
@ -1256,11 +1324,67 @@ void spawnEntity(VariantEntityData entity) {
Debug("Warn: Could not find entity (classname=%s)", entity.model);
} else if(StrContains(entity.type, "_car") != -1) {
SpawnCar(entity);
} else if(StrEqual(entity.type, "move_rope")) {
if(!PrecacheModel(entity.model)) {
LogError("Precache of entity model \"%s\" with type \"%s\" failed", entity.model, entity.type);
return;
} else if(entity.keyframes == null) {
// should not happen
LogError("rope entity has no keyframes", entity.keyframes);
return;
}
CreateRope(entity);
} else {
LogError("Unknown entity type \"%s\"", entity.type);
}
}
int CreateRope(VariantEntityData data) {
char targetName[32], nextKey[32];
Format(targetName, sizeof(targetName), "randomizer_rope%d", _ropeIndex);
Format(nextKey, sizeof(nextKey), "randomizer_rope%d_0", _ropeIndex);
int entity = _CreateRope("move_rope", targetName, nextKey, data.model, data.origin);
float pos[3];
for(int i = 0; i < data.keyframes.Length; i++) {
nextKey[0] = '\0';
Format(targetName, sizeof(targetName), "randomizer_rope%d_%d", _ropeIndex, i);
if(i < data.keyframes.Length - 1) {
Format(nextKey, sizeof(nextKey), "randomizer_rope%d_%d", _ropeIndex, i + 1);
}
data.keyframes.GetArray(i, pos, sizeof(pos));
_CreateRope("move_rope", targetName, nextKey, data.model, pos);
}
Debug("created rope #%d with %d keyframes. entid:%d", _ropeIndex, data.keyframes.Length, entity);
_ropeIndex++;
return entity;
}
int _CreateRope(const char[] type, const char[] targetname, const char[] nextKey, const char[] texture, const float origin[3]) {
int entity = CreateEntityByName(type);
if(entity == -1) return -1;
Debug("_createRope(\"%s\", \"%s\", \"%s\", \"%s\", %.0f %.0f %.0f", type, targetname, nextKey, texture, origin[0], origin[1], origin[2]);
DispatchKeyValue(entity, "targetname", targetname);
DispatchKeyValue(entity, "NextKey", nextKey);
DispatchKeyValue(entity, "RopeMaterial", texture);
DispatchKeyValueInt(entity, "Type", 0);
DispatchKeyValueFloat(entity, "Width", 2.0);
DispatchKeyValueInt(entity, "Breakable", 0);
DispatchKeyValueInt(entity, "Slack", 0);
DispatchKeyValueInt(entity, "Type", 0);
DispatchKeyValueInt(entity, "TextureScale", 2);
DispatchKeyValueInt(entity, "Subdiv", 2);
DispatchKeyValueInt(entity, "MoveSpeed", 0);
DispatchKeyValueInt(entity, "Dangling", 0);
DispatchKeyValueInt(entity, "Collide", 0);
DispatchKeyValueInt(entity, "Barbed", 0);
DispatchKeyValue(entity, "PositionInterpolator", "2");
// DispatchKeyValueFloat( entity, "m_RopeLength", 10.0 );
TeleportEntity(entity, origin, NULL_VECTOR, NULL_VECTOR);
if(!DispatchSpawn(entity)) {
return -1;
}
return entity;
}
void Debug(const char[] format, any ...) {
#if defined DEBUG_SCENE_PARSE
char buffer[192];
@ -1296,8 +1420,9 @@ void Cleanup() {
int entity = -1;
char targetname[128];
while((entity = FindEntityByClassname(entity, "*")) != INVALID_ENT_REFERENCE) {
if(!IsValidEntity(entity)) return;
GetEntPropString(entity, Prop_Data, "m_iName", targetname, sizeof(targetname));
if(StrContains(targetname, "randomizer_car") != -1) {
if(StrContains(targetname, "randomizer_") != -1) {
RemoveEntity(entity);
}
}