Skip to content

Commit

Permalink
Merge pull request #4120 from myk002/myk_reveal_secrets
Browse files Browse the repository at this point in the history
[reveal] don't reveal triggers
  • Loading branch information
myk002 authored Dec 31, 2023
2 parents 2ede4dc + b3526a7 commit 419e41d
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 10 deletions.
1 change: 1 addition & 0 deletions docs/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 13 additions & 2 deletions docs/plugins/reveal.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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``
Expand All @@ -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.
56 changes: 48 additions & 8 deletions plugins/reveal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand Down

0 comments on commit 419e41d

Please sign in to comment.