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

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,9 +20,11 @@ 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);
SetVariantString("!activator");
AcceptEntityInput(glass, "SetParent", vehicle);
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);
}
}