Merge pull request #4120 from myk002/myk_reveal_secrets

[reveal] don't reveal triggers
develop
Myk 2023-12-31 11:38:09 -08:00 committed by GitHub
commit 419e41da66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 10 deletions

@ -57,6 +57,7 @@ Template for new versions:
- `sort`: search and sort for the "choose unit to elevate to the barony" screen. units are sorted by the number of item preferences they have and the units are annotated with the items that they have preferences for
## Fixes
- `reveal`: now avoids revealing blocks that contain divine treasures, encased horrors, and deep vein hollows (so the surprise triggers are not triggered prematurely)
- `sort`: fix mouse clicks falling through the squad assignment overlay panel when clicking on the panel but not on a clickable widget
- `sort`: fix potential crash when removing jobs directly from the Tasks info screen
- `misery`: fix error when changing the misery factor

@ -32,8 +32,8 @@ Usage
``reveal [hell|demon]``
Reveal the whole map. If ``hell`` is specified, also reveal HFS areas, but
you are required to run ``unreveal`` before unpausing is allowed in order
to prevent the demons from spawning. If you really want to unpause with hell
revealed, specify ``demon`` instead of ``hell``.
to prevent the demons (or treasures) from spawning. If you really want to
unpause with secrets revealed, specify ``demon`` instead of ``hell``.
``unreveal``
Reverts the effects of ``reveal``.
``revtoggle``
@ -54,3 +54,14 @@ Usage
forced by `reveal` ``hell``. This is nice for digging under rivers. Use
``nopause 1`` to prevent pausing and ``nopause 0`` to allow pausing like
normal.
Note
----
Sometimes, the map generates secret hollows adjacent to caverns in such a way
that the ceiling of the hollow collapses on the first tick of the embark,
leaving the hollow exposed to the caverns. In this case, the secret event will
be triggered as soon as the cavern is discovered and that tile is unhidden.
This would happen anyway even if you don't use `reveal`, but be aware that it
is possible to trigger *some* events when you run `reveal`, even without the
``hell`` option.

@ -5,9 +5,9 @@
#include "Core.h"
#include "Console.h"
#include "Export.h"
#include "PluginManager.h"
#include "modules/EventManager.h"
#include "modules/Maps.h"
#include "modules/World.h"
#include "modules/MapCache.h"
@ -17,8 +17,13 @@
#include "df/block_square_event_frozen_liquidst.h"
#include "df/construction.h"
#include "df/deep_vein_hollow.h"
#include "df/divine_treasure.h"
#include "df/encased_horror.h"
#include "df/world.h"
#include <unordered_set>
using MapExtras::MapCache;
using std::string;
@ -33,15 +38,23 @@ DFHACK_PLUGIN_IS_ENABLED(is_active);
REQUIRE_GLOBAL(world);
/*
* Anything that might reveal Hell is unsafe.
* Anything that might reveal Hell or trigger gemstone pillar events is unsafe.
*/
bool isSafe(df::coord c)
bool isSafe(df::coord c, const std::unordered_set<df::coord> & trigger_cache)
{
// convert to block coordinates
c.x >>= 4;
c.y >>= 4;
// Don't reveal blocks that contain trigger events
if (trigger_cache.contains(c))
return false;
t_feature local_feature;
t_feature global_feature;
// get features of block
// error -> obviously not safe to manipulate
if(!Maps::ReadFeatures(c.x >> 4,c.y >> 4,c.z,&local_feature,&global_feature))
if(!Maps::ReadFeatures(c.x,c.y,c.z,&local_feature,&global_feature))
return false;
// Adamantine tubes and temples lead to Hell
@ -154,13 +167,13 @@ command_result nopause (color_ostream &out, vector <string> & parameters)
return CR_OK;
}
void revealAdventure(color_ostream &out)
void revealAdventure(color_ostream &out, const std::unordered_set<df::coord> & trigger_cache)
{
for (size_t i = 0; i < world->map.map_blocks.size(); i++)
{
df::map_block *block = world->map.map_blocks[i];
// in 'no-hell'/'safe' mode, don't reveal blocks with hell and adamantine
if (!isSafe(block->map_pos))
if (!isSafe(block->map_pos, trigger_cache))
continue;
designations40d & designations = block->designation;
// for each tile in block
@ -175,6 +188,28 @@ void revealAdventure(color_ostream &out)
out.print("Local map revealed.\n");
}
static void cache_tiles(const df::coord_path & tiles, std::unordered_set<df::coord> & trigger_cache)
{
size_t num_tiles = tiles.size();
for (size_t idx = 0; idx < num_tiles; ++idx)
{
df::coord pos = tiles[idx];
pos.x >>= 4;
pos.y >>= 4;
trigger_cache.insert(pos);
}
}
static void initialize_trigger_cache(std::unordered_set<df::coord> & trigger_cache)
{
for (auto & horror : world->encased_horrors)
cache_tiles(horror->tiles, trigger_cache);
for (auto & hollow : world->deep_vein_hollows)
cache_tiles(hollow->tiles, trigger_cache);
for (auto & treasure : world->divine_treasures)
cache_tiles(treasure->tiles, trigger_cache);
}
command_result reveal(color_ostream &out, vector<string> & params)
{
bool no_hell = true;
@ -211,11 +246,16 @@ command_result reveal(color_ostream &out, vector<string> & params)
out.printerr("Map is not available!\n");
return CR_FAILURE;
}
size_t initial_buckets = 2 * (world->encased_horrors.size() + world->divine_treasures.size() + world->deep_vein_hollows.size());
std::unordered_set<df::coord> trigger_cache(initial_buckets);
initialize_trigger_cache(trigger_cache);
t_gamemodes gm;
World::ReadGameMode(gm);
if(gm.g_mode == game_mode::ADVENTURE)
{
revealAdventure(out);
revealAdventure(out, trigger_cache);
return CR_OK;
}
if(gm.g_mode != game_mode::DWARF)
@ -230,7 +270,7 @@ command_result reveal(color_ostream &out, vector<string> & params)
{
df::map_block *block = world->map.map_blocks[i];
// in 'no-hell'/'safe' mode, don't reveal blocks with hell and adamantine
if (no_hell && !isSafe(block->map_pos))
if (no_hell && !isSafe(block->map_pos, trigger_cache))
continue;
hideblock hb;
hb.c = block->map_pos;