mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-05 19:53:20 +00:00
230 lines
7.9 KiB
SourcePawn
230 lines
7.9 KiB
SourcePawn
bool IsTraverseMapA(const char[] map) {
|
|
return String_EndsWith(map, "_a");
|
|
}
|
|
bool IsTraverseMapB(const char[] map) {
|
|
// c4m1_milltown_a was added twice so _escape can pop it off and re-use
|
|
return StrEqual(map, "c4m5_milltown_escape") || String_EndsWith(map, "_b");
|
|
}
|
|
|
|
public bool LoadRunGlobalMap(const char[] map, int flags) {
|
|
// Unless FLAG_IGNORE_TRAVERSE_STORE, if the map is the _b variant, then load the stored _a value
|
|
SceneSelection selection;
|
|
// Only load map data if we don't already have it
|
|
if(g_MapData.scenes == null || g_selection == null || flags & view_as<int>(FLAG_REFRESH)) {
|
|
if(~flags & view_as<int>(FLAG_IGNORE_TRAVERSE_STORE) && IsTraverseMapB(map) ) {
|
|
Log("LoadRunGlobal: Trying to load traverse selection");
|
|
TraverseData traverse;
|
|
if(PopTraverseSelection(traverse)) {
|
|
Debug("traverse map: %s", traverse.map);
|
|
// Try Load the A variant
|
|
if(LoadGlobalMapData(traverse.map, flags)) {
|
|
selection = view_as<SceneSelection>(traverse.selection);
|
|
}
|
|
}
|
|
}
|
|
if(selection == null) {
|
|
// This is called if not traverse map or previous data not found
|
|
Log("LoadRunGlobal: Loading & generating selection");
|
|
if(!LoadGlobalMapData(map, flags)) {
|
|
return false;
|
|
}
|
|
selection = selectScenes(g_MapData, flags);
|
|
}
|
|
}
|
|
if(selection == null) {
|
|
LogError("LoadRunGlobalMap: No selection was loaded");
|
|
}
|
|
|
|
g_selection = selection;
|
|
|
|
return g_MapData.ApplySelection(selection, flags);
|
|
}
|
|
|
|
void trySelectScene(SceneSelection selection, SceneData scene, int flags) {
|
|
// Use the .chance field unless FLAG_ALL_SCENES or FLAG_FORCE_ACTIVE is set
|
|
if(~flags & view_as<int>(FLAG_ALL_SCENES) && ~flags & view_as<int>(FLAG_FORCE_ACTIVE) && GetURandomFloat() > scene.chance) {
|
|
return;
|
|
}
|
|
|
|
if(scene.variants.Length == 0) {
|
|
LogError("Warn: No variants were found for scene \"%s\"", scene.name);
|
|
return;
|
|
}
|
|
|
|
// TODO: select variant...
|
|
SelectedSceneData aScene;
|
|
aScene.name = scene.name;
|
|
aScene.selectedVariantIndexes = new ArrayList();
|
|
|
|
ArrayList choices = new ArrayList();
|
|
SceneVariantData choice;
|
|
int chosenIndex;
|
|
Debug("Scene %s has %d variants", scene.name, scene.variants.Length);
|
|
// Weighted random: Push N times dependent on weight
|
|
for(int i = 0; i < scene.variants.Length; i++) {
|
|
scene.variants.GetArray(i, choice);
|
|
if(flags & view_as<int>(FLAG_ALL_VARIANTS)) {
|
|
aScene.selectedVariantIndexes.Push(i);
|
|
} else {
|
|
if(choice.weight <= 0) {
|
|
PrintToServer("Warn: Variant %d in scene %s has invalid weight", i, scene.name);
|
|
continue;
|
|
}
|
|
for(int c = 0; c < choice.weight; c++) {
|
|
choices.Push(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(flags & view_as<int>(FLAG_ALL_VARIANTS)) {
|
|
|
|
} else if(choices.Length > 0) {
|
|
// Pick a random variant from list
|
|
chosenIndex = GetURandomInt() % choices.Length;
|
|
chosenIndex = choices.Get(chosenIndex);
|
|
Log("Chosen scene \"%s\" with variant #%d", scene.name, chosenIndex);
|
|
|
|
aScene.selectedVariantIndexes.Push(chosenIndex);
|
|
}
|
|
delete choices;
|
|
|
|
selection.AddScene(aScene);
|
|
}
|
|
|
|
void selectGroups(SceneSelection selection, MapData data, int flags) {
|
|
StringMapSnapshot snapshot = data.groups.Snapshot();
|
|
char key[MAX_SCENE_NAME_LENGTH];
|
|
ArrayList groupList;
|
|
SceneData scene;
|
|
for(int i = 0; i < snapshot.Length; i++) {
|
|
snapshot.GetKey(i, key, sizeof(key));
|
|
data.groups.GetValue(key, groupList);
|
|
|
|
// Select a random scene from the group:
|
|
int index = GetURandomInt() % groupList.Length;
|
|
index = groupList.Get(index);
|
|
data.scenes.GetArray(index, scene);
|
|
|
|
Debug("Selected scene \"%s\" for group %s (%d members)", scene.name, key, groupList.Length);
|
|
trySelectScene(selection, scene, flags);
|
|
delete groupList;
|
|
}
|
|
delete snapshot;
|
|
}
|
|
|
|
void selectForcedScenes(SceneSelection selection, MapData data, int flags) {
|
|
// Traverse active scenes, loading any other scene it requires (via .force_scenes)
|
|
SelectedSceneData aScene;
|
|
SceneVariantData choice;
|
|
SceneData scene;
|
|
// list of scenes that will need to be forced if not already:
|
|
ArrayList forcedScenes = new ArrayList(ByteCountToCells(MAX_SCENE_NAME_LENGTH));
|
|
char key[MAX_SCENE_NAME_LENGTH];
|
|
for(int i = 0; i < selection.Count; i++) {
|
|
selection.Get(i, aScene);
|
|
// Load scene from active scene entry
|
|
if(!data.scenesKv.GetArray(aScene.name, scene, sizeof(scene))) {
|
|
// this shouldn't happen
|
|
Log("WARN: scene \"%s\" not found in scene selection", aScene.name);
|
|
// can't find scene, ignore
|
|
continue;
|
|
}
|
|
for(int v = 0; v < aScene.selectedVariantIndexes.Length; v++) {
|
|
aScene.selectedVariantIndexes.GetArray(v, choice);
|
|
// If the choice has forced scenes
|
|
if(choice.forcedScenes != null) {
|
|
// Add each scene to the list to be added
|
|
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 < data.activeScenes.Length; j++) {
|
|
data.activeScenes.GetArray(j, aScene);
|
|
if(StrEqual(aScene.name, key)) {
|
|
isSceneAlreadyLoaded = true;
|
|
break;
|
|
}
|
|
}
|
|
if(isSceneAlreadyLoaded) continue;
|
|
data.scenesKv.GetArray(key, scene, sizeof(scene));
|
|
trySelectScene(selection, scene, flags | view_as<int>(FLAG_FORCE_ACTIVE));
|
|
}
|
|
delete forcedScenes;
|
|
}
|
|
|
|
// Selects what scenes and its variants to apply and returns list - does not activate
|
|
SceneSelection selectScenes(MapData data, int flags = 0) {
|
|
SceneData scene;
|
|
SceneSelection selection = new SceneSelection();
|
|
|
|
Profiler profiler = new Profiler();
|
|
profiler.Start();
|
|
|
|
for(int i = 0; i < data.scenes.Length; i++) {
|
|
data.scenes.GetArray(i, scene);
|
|
if(scene.group[0] == '\0') {
|
|
trySelectScene(selection, scene, flags);
|
|
}
|
|
}
|
|
selectGroups(selection, data, flags);
|
|
selectForcedScenes(selection, data, flags);
|
|
|
|
profiler.Stop();
|
|
Log("Done generating selection in %.4f seconds", profiler.Time);
|
|
return selection;
|
|
}
|
|
|
|
void spawnGascans(MapData data) {
|
|
if(data.gascanSpawners != null && data.gascanSpawners.Length > 0) {
|
|
// Iterate through every gascan until we run out - picking a random spawner each time
|
|
int entity = -1;
|
|
char targetname[9];
|
|
GascanSpawnerData spawner;
|
|
int spawnerCount = data.gascanSpawners.Length;
|
|
int count;
|
|
while((entity = FindEntityByClassname(entity, "weapon_gascan")) != INVALID_ENT_REFERENCE) {
|
|
GetEntPropString(entity, Prop_Data, "m_iName", targetname, sizeof(targetname));
|
|
int hammerid = GetEntProp(entity, Prop_Data, "m_iHammerID");
|
|
int glowColor = GetEntProp(entity, Prop_Send, "m_glowColorOverride"); // check if white
|
|
if(hammerid == 0 && glowColor == 16777215 && targetname[0] == '\0' && !g_gascanSpawners.ContainsKey(entity)) {
|
|
// Found a valid gascan, apply a random spawner
|
|
int spawnerIndex = GetRandomInt(0, data.gascanSpawners.Length - 1);
|
|
data.gascanSpawners.GetArray(spawnerIndex, spawner);
|
|
data.gascanSpawners.Erase(spawnerIndex); // only want one can to use this spawner
|
|
|
|
AssignGascan(entity, spawner);
|
|
count++;
|
|
}
|
|
}
|
|
Debug("Assigned %d gascans to %d spawners", count, spawnerCount);
|
|
}
|
|
}
|
|
|
|
void activateVariant(SceneVariantData choice, int flags) {
|
|
#pragma unused flags
|
|
VariantEntityData entity;
|
|
for(int i = 0; i < choice.entities.Length; i++) {
|
|
choice.entities.GetArray(i, entity);
|
|
spawnEntity(entity);
|
|
}
|
|
|
|
if(choice.inputsList.Length > 0) {
|
|
VariantInputData input;
|
|
for(int i = 0; i < choice.inputsList.Length; i++) {
|
|
choice.inputsList.GetArray(i, input);
|
|
input.Trigger();
|
|
}
|
|
}
|
|
}
|