Skip to content

Commit

Permalink
Modify hordes through overmap editor
Browse files Browse the repository at this point in the history
  • Loading branch information
RenechCDDA committed Sep 7, 2024
1 parent e398be1 commit fa60080
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 12 deletions.
7 changes: 7 additions & 0 deletions data/raw/keybindings.json
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,13 @@
"name": "Teleport to cursor",
"bindings": [ { "input_method": "keyboard_any", "key": "d" } ]
},
{
"type": "keybinding",
"id": "MODIFY_HORDE",
"category": "OVERMAP",
"name": "Modify existing horde or place new one",
"bindings": [ { "input_method": "keyboard_any", "key": "p" } ]
},
{
"type": "keybinding",
"name": "View missions",
Expand Down
1 change: 1 addition & 0 deletions src/debug_menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ void wishitem( Character *you = nullptr );
void wishitem( Character *you, const tripoint & );
void wishitem( Character *you, const tripoint_bub_ms & );
void wishmonster( const std::optional<tripoint> &p );
void wishmonstergroup( tripoint_abs_omt &loc );
void wishmutate( Character *you );
void wishbionics( Character *you );
/*
Expand Down
17 changes: 17 additions & 0 deletions src/overmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7553,6 +7553,23 @@ void overmap::debug_force_add_group( const mongroup &group )
add_mon_group( group, 1 );
}

std::vector<std::reference_wrapper<mongroup>> overmap::debug_unsafe_get_groups_at(
tripoint_abs_omt &loc )
{
point_abs_om overmap;
tripoint_om_omt omt_within_overmap;
std::tie( overmap, omt_within_overmap ) = project_remain<coords::om>( loc );
tripoint_om_sm om_sm_pos = project_to<coords::sm>( omt_within_overmap );

std::vector<std::reference_wrapper <mongroup>> groups_at;
for( std::pair<const tripoint_om_sm, mongroup> &pair : zg ) {
if( pair.first == om_sm_pos ) {
groups_at.emplace_back( pair.second );
}
}
return groups_at;
}

void overmap::add_mon_group( const mongroup &group )
{
zg.emplace( group.rel_pos(), group );
Expand Down
1 change: 1 addition & 0 deletions src/overmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ class overmap

// DEBUG ONLY!
void debug_force_add_group( const mongroup &group );
std::vector<std::reference_wrapper<mongroup>> debug_unsafe_get_groups_at( tripoint_abs_omt &loc );
private:
/**
* Iterate over the overmap and place the quota of specials.
Expand Down
90 changes: 90 additions & 0 deletions src/overmap_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "cuboid_rectangle.h"
#include "cursesdef.h"
#include "display.h"
#include "debug_menu.h"
#include "game.h"
#include "game_constants.h"
#include "game_ui.h"
Expand Down Expand Up @@ -1150,6 +1151,7 @@ static void draw_om_sidebar( ui_adaptor &ui,
print_hint( "PLACE_SPECIAL", c_light_blue );
print_hint( "SET_SPECIAL_ARGS", c_light_blue );
print_hint( "LONG_TELEPORT", c_light_blue );
print_hint( "MODIFY_HORDE", c_light_blue );
++y;
}

Expand Down Expand Up @@ -1626,6 +1628,89 @@ static void set_special_args( tripoint_abs_omt &curs )
*maybe_args = args;
}

static void modify_horde_func( tripoint_abs_omt &curs )
{
overmap &map_at_cursor = overmap_buffer.get( project_to<coords::om>( curs ).xy() );
std::vector<std::reference_wrapper<mongroup>> hordes =
map_at_cursor.debug_unsafe_get_groups_at( curs );
if( hordes.empty() ) {
if( !query_yn( _( "No hordes there. Would you like to make a new horde?" ) ) ) {
return;
} else {
debug_menu::wishmonstergroup( curs );
return;
}
}
uilist horde_list;
int entry_num = 0;
for( auto &blah : hordes ) {
mongroup &mg = blah.get();
// We do some special handling here to provide the information in as simple a way as possible
// emulates horde behavior
int displayed_monster_num = mg.monsters.empty() ? mg.population : mg.monsters.size();
std::string horde_description = string_format( _( "group(type: %s) with %d monsters" ),
mg.type.c_str(), displayed_monster_num );
horde_list.addentry( entry_num, true, -1, horde_description );
}
horde_list.query();
int &selected_group = horde_list.ret;
if( selected_group < 0 || static_cast<size_t>( selected_group ) > hordes.size() ) {
return;
}
mongroup &chosen_group = hordes[selected_group];

uilist smenu;
smenu.addentry( 0, true, 'I', _( "Set horde's interest (in %%)" ) );
smenu.addentry( 1, true, 'D', _( "Set horde's destination" ) );
smenu.addentry( 2, true, 'P', _( "Modify horde's population" ) );
smenu.addentry( 3, true, 'M', _( "Add a new monster to the horde" ) );
smenu.addentry( 4, true, 'M', _( "Set horde behavior" ) );
smenu.addentry( 5, true, 'M', _( "Set horde's boolean values" ) );
smenu.query();
int new_value = 0;
tripoint_abs_omt horde_destination = tripoint_abs_omt_zero;
switch( smenu.ret ) {
case 0:
query_int( new_value, _( "Set interest to what value? Currently %d" ), chosen_group.interest );
chosen_group.set_interest( new_value );
break;
case 1:
popup( _( "Select a target destination for the horde." ) );
horde_destination = ui::omap::choose_point( true );
if( horde_destination == overmap::invalid_tripoint || horde_destination == tripoint_abs_omt_zero ) {
break;
}
chosen_group.target = project_to<coords::sm>( horde_destination ).xy();
break;
case 2:
query_int( new_value, _( "Set population to what value? Currently %d" ), chosen_group.population );
chosen_group.population = new_value;
break;
case 3:
// FIXME: not implemented
popup( "Please wait warmly, contributors are working on it." );
break;
case 4:
// Screw it we hardcode a popup, if you really want to use this you're welcome to improve it
popup( _( "Set behavior to which enum value? Currently %d. \nAccepted values:\n0 = none,\n1 = city,\n2=roam,\n3=nemesis" ),
static_cast<int>( chosen_group.behaviour ) );
query_int( new_value, "" );
chosen_group.behaviour = static_cast<mongroup::horde_behaviour>( new_value );
break;
case 5:
// One day we'll be able to simply convert booleans to strings...
chosen_group.horde = query_yn(
_( "Set group's \"horde\" value to true? (Select no to set to false) \nCurrently %s" ),
chosen_group.horde ? _( "true" ) : _( "false" ) );
chosen_group.dying = query_yn(
_( "Set group's \"dying\" value to true? (Select no to set to false) \nCurrently %s" ),
chosen_group.dying ? _( "true" ) : _( "false" ) );
break;
default:
break;
}
}

static std::vector<tripoint_abs_omt> get_overmap_path_to( const tripoint_abs_omt &dest,
bool driving )
{
Expand Down Expand Up @@ -1806,6 +1891,7 @@ static tripoint_abs_omt display()
ictxt.register_action( "PLACE_SPECIAL" );
ictxt.register_action( "SET_SPECIAL_ARGS" );
ictxt.register_action( "LONG_TELEPORT" );
ictxt.register_action( "MODIFY_HORDE" );
}
ictxt.register_action( "QUIT" );
std::string action;
Expand Down Expand Up @@ -2011,6 +2097,9 @@ static tripoint_abs_omt display()
g->place_player_overmap( curs );
add_msg( _( "You teleport to submap %s." ), curs.to_string() );
action = "QUIT";
} else if( action == "MODIFY_HORDE" ) {
modify_horde_func( curs );
action = "QUIT";
} else if( action == "MISSIONS" ) {
g->list_missions();
}
Expand Down Expand Up @@ -2278,6 +2367,7 @@ void ui::omap::display()
{
g->overmap_data = overmap_ui::overmap_draw_data_t(); //reset data
g->overmap_data.origin_pos = get_player_character().global_omt_location();
g->overmap_data.debug_editor = debug_mode; // always display debug editor if game is in debug mode
overmap_ui::display();
}

Expand Down
67 changes: 55 additions & 12 deletions src/wish.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@
#include "item_factory.h"
#include "itype.h"
#include "localized_comparator.h"
#include "overmap.h"
#include "overmapbuffer.h"
#include "map.h"
#include "mongroup.h"
#include "monster.h"
#include "monstergenerator.h"
#include "mtype.h"
Expand Down Expand Up @@ -713,26 +716,66 @@ class wish_monster_callback: public uilist_callback
~wish_monster_callback() override = default;
};

static void setup_wishmonster( uilist &pick_a_monster, std::vector<const mtype *> &mtypes )
{
pick_a_monster.desired_bounds = { -1.0, -1.0, 1.0, 1.0 };
pick_a_monster.selected = uistate.wishmonster_selected;
int i = 0;
for( const mtype &montype : MonsterGenerator::generator().get_all_mtypes() ) {
pick_a_monster.addentry( i, true, 0, montype.nname() );
pick_a_monster.entries[i].extratxt.txt = montype.sym;
pick_a_monster.entries[i].extratxt.color = montype.color;
pick_a_monster.entries[i].extratxt.left = 1;
++i;
mtypes.push_back( &montype );
}
}

void debug_menu::wishmonstergroup( tripoint_abs_omt &loc )
{
mongroup new_group;
// Just in case, we manually set some values
new_group.abs_pos = project_to<coords::sm>( loc );
new_group.target = new_group.abs_pos.xy();
new_group.population = 1; // no support for population-based groups... yet
new_group.horde = true;


std::vector<const mtype *> mtypes;
uilist new_mon_selection;
setup_wishmonster( new_mon_selection, mtypes );
wish_monster_callback cb( mtypes );
new_mon_selection.callback = &cb;
new_mon_selection.query();
int &selected = new_mon_selection.ret;
if( selected < 0 || static_cast<size_t>( selected ) >= mtypes.size() ) {
return;
}
const mtype_id &mon_type = mtypes[ selected ]->id;
for( int i = 0; i < cb.group; i++ ) {
monster new_mon( mon_type );
if( cb.friendly ) {
new_mon.friendly = -1;
new_mon.add_effect( effect_pet, 1_turns, true );
}
if( cb.hallucination ) {
new_mon.hallucination = true;
}
new_group.monsters.emplace_back( new_mon );
}
overmap &there = overmap_buffer.get( project_to<coords::om>( loc ).xy() );
there.debug_force_add_group( new_group );
}

void debug_menu::wishmonster( const std::optional<tripoint> &p )
{
std::vector<const mtype *> mtypes;

uilist wmenu;
wmenu.desired_bounds = { -1.0, -1.0, 1.0, 1.0 };
wmenu.selected = uistate.wishmonster_selected;
setup_wishmonster( wmenu, mtypes );
wish_monster_callback cb( mtypes );
wmenu.callback = &cb;

int i = 0;
for( const mtype &montype : MonsterGenerator::generator().get_all_mtypes() ) {
wmenu.addentry( i, true, 0, montype.nname() );
wmenu.entries[i].extratxt.txt = montype.sym;
wmenu.entries[i].extratxt.color = montype.color;
wmenu.entries[i].extratxt.left = 1;
++i;
mtypes.push_back( &montype );
}

do {
wmenu.query();
if( wmenu.ret >= 0 ) {
Expand Down

0 comments on commit fa60080

Please sign in to comment.