Skip to content

Commit

Permalink
Update events to account for ability to swap avatars (debug or upon d…
Browse files Browse the repository at this point in the history
…eath) (#63488)
  • Loading branch information
cake-pie authored Mar 22, 2023
1 parent 4caf015 commit 82b6ecb
Show file tree
Hide file tree
Showing 15 changed files with 355 additions and 240 deletions.
11 changes: 9 additions & 2 deletions data/json/statistics.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@
{
"id": "avatar_id",
"type": "event_statistic",
"stat_type": "unique_value",
"event_type": "game_start",
"stat_type": "last_value",
"event_type": "game_avatar_new",
"field": "avatar_id"
},
{
"id": "last_words",
"type": "event_statistic",
"stat_type": "last_value",
"event_type": "game_avatar_death",
"field": "last_words"
},
{
"id": "avatar_wakes_up",
"type": "event_transformation",
Expand Down
10 changes: 7 additions & 3 deletions src/avatar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ static void swap_npc( npc &one, npc &two, npc &tmp )
two = std::move( tmp );
}

void avatar::control_npc( npc &np )
void avatar::control_npc( npc &np, const bool debug )
{
if( !np.is_player_ally() ) {
debugmsg( "control_npc() called on non-allied npc %s", np.name );
Expand Down Expand Up @@ -202,9 +202,13 @@ void avatar::control_npc( npc &np )
const bool z_level_changed = g->vertical_shift( posz() );
g->update_map( *this, z_level_changed );
character_mood_face( true );

profession_id prof_id = prof ? prof->ident() : profession::generic()->ident();
get_event_bus().send<event_type::game_avatar_new>( /*is_new_game=*/false, debug,
getID(), name, male, prof_id, custom_profession );
}

void avatar::control_npc_menu()
void avatar::control_npc_menu( const bool debug )
{
std::vector<shared_ptr_fast<npc>> followers;
uilist charmenu;
Expand All @@ -225,7 +229,7 @@ void avatar::control_npc_menu()
if( charmenu.ret < 0 || static_cast<size_t>( charmenu.ret ) >= followers.size() ) {
return;
}
get_avatar().control_npc( *followers[charmenu.ret] );
get_avatar().control_npc( *followers[charmenu.ret], debug );
}

void avatar::longpull( const std::string &name )
Expand Down
4 changes: 2 additions & 2 deletions src/avatar.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,11 @@ class avatar : public Character
* Makes the avatar "take over" the given NPC, while the current avatar character
* becomes an NPC.
*/
void control_npc( npc & );
void control_npc( npc &, bool debug = false );
/**
* Open a menu to choose the NPC to take over.
*/
void control_npc_menu();
void control_npc_menu( bool debug = false );
using Character::query_yn;
bool query_yn( const std::string &mes ) const override;

Expand Down
2 changes: 1 addition & 1 deletion src/debug_menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1377,7 +1377,7 @@ static void spawn_nested_mapgen()

static void control_npc_menu()
{
get_avatar().control_npc_menu();
get_avatar().control_npc_menu( true );
}

static void character_edit_stats_menu( Character &you )
Expand Down
193 changes: 5 additions & 188 deletions src/do_turn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "scent_map.h"
#include "sdlsound.h"
#include "string_input_popup.h"
#include "stats_tracker.h"
#include "timed_event.h"
#include "ui_manager.h"
#include "vehicle.h"
Expand All @@ -47,13 +48,9 @@ static const efftype_id effect_npc_suspend( "npc_suspend" );
static const efftype_id effect_ridden( "ridden" );
static const efftype_id effect_sleep( "sleep" );

static const itype_id itype_holybook_bible1( "holybook_bible1" );
static const itype_id itype_holybook_bible2( "holybook_bible2" );
static const itype_id itype_holybook_bible3( "holybook_bible3" );
static const event_statistic_id event_statistic_last_words( "last_words" );

static const trait_id trait_CANNIBAL( "CANNIBAL" );
static const trait_id trait_HAS_NEMESIS( "HAS_NEMESIS" );
static const trait_id trait_PSYCHOPATH( "PSYCHOPATH" );

#if defined(__ANDROID__)
extern std::map<std::string, std::list<input_event>> quick_shortcuts_map;
Expand Down Expand Up @@ -85,197 +82,17 @@ bool cleanup_at_end()

// and the overmap, and the local map.
g->save_maps(); //Omap also contains the npcs who need to be saved.
}

if( g->uquit == QUIT_DIED || g->uquit == QUIT_SUICIDE ) {
std::vector<std::string> vRip;

int iMaxWidth = 0;
int iNameLine = 0;
int iInfoLine = 0;

if( u.has_amount( itype_holybook_bible1, 1 ) || u.has_amount( itype_holybook_bible2, 1 ) ||
u.has_amount( itype_holybook_bible3, 1 ) ) {
if( !( u.has_trait( trait_CANNIBAL ) || u.has_trait( trait_PSYCHOPATH ) ) ) {
vRip.emplace_back( " _______ ___" );
vRip.emplace_back( " < `/ |" );
vRip.emplace_back( " > _ _ (" );
vRip.emplace_back( " | |_) | |_) |" );
vRip.emplace_back( " | | \\ | | |" );
vRip.emplace_back( " ______.__%_| |_________ __" );
vRip.emplace_back( " _/ \\| |" );
iNameLine = vRip.size();
vRip.emplace_back( "| <" );
vRip.emplace_back( "| |" );
iMaxWidth = utf8_width( vRip.back() );
vRip.emplace_back( "| |" );
vRip.emplace_back( "|_____.-._____ __/|_________|" );
vRip.emplace_back( " | |" );
iInfoLine = vRip.size();
vRip.emplace_back( " | |" );
vRip.emplace_back( " | <" );
vRip.emplace_back( " | |" );
vRip.emplace_back( " | _ |" );
vRip.emplace_back( " |__/ |" );
vRip.emplace_back( " % / `--. |%" );
vRip.emplace_back( " * .%%| -< @%%%" ); // NOLINT(cata-text-style)
vRip.emplace_back( " `\\%`@| |@@%@%%" );
vRip.emplace_back( " .%%%@@@|% ` % @@@%%@%%%%" );
vRip.emplace_back( " _.%%%%%%@@@@@@%%%__/\\%@@%%@@@@@@@%%%%%%" );

} else {
vRip.emplace_back( " _______ ___" );
vRip.emplace_back( " | \\/ |" );
vRip.emplace_back( " | |" );
vRip.emplace_back( " | |" );
iInfoLine = vRip.size();
vRip.emplace_back( " | |" );
vRip.emplace_back( " | |" );
vRip.emplace_back( " | |" );
vRip.emplace_back( " | |" );
vRip.emplace_back( " | <" );
vRip.emplace_back( " | _ |" );
vRip.emplace_back( " |__/ |" );
vRip.emplace_back( " ______.__%_| |__________ _" );
vRip.emplace_back( " _/ \\| \\" );
iNameLine = vRip.size();
vRip.emplace_back( "| <" );
vRip.emplace_back( "| |" );
iMaxWidth = utf8_width( vRip.back() );
vRip.emplace_back( "| |" );
vRip.emplace_back( "|_____.-._______ __/|__________|" );
vRip.emplace_back( " % / `_-. _ |%" );
vRip.emplace_back( " * .%%| |_) | |_)< @%%%" ); // NOLINT(cata-text-style)
vRip.emplace_back( " `\\%`@| | \\ | | |@@%@%%" );
vRip.emplace_back( " .%%%@@@|% ` % @@@%%@%%%%" );
vRip.emplace_back( " _.%%%%%%@@@@@@%%%__/\\%@@%%@@@@@@@%%%%%%" );
}
} else {
vRip.emplace_back( R"( _________ ____ )" );
vRip.emplace_back( R"( _/ `/ \_ )" );
vRip.emplace_back( R"( _/ _ _ \_. )" );
vRip.emplace_back( R"( _%\ |_) | |_) \_ )" );
vRip.emplace_back( R"( _/ \/ | \ | | \_ )" );
vRip.emplace_back( R"( _/ \_ )" );
vRip.emplace_back( R"(| |)" );
iNameLine = vRip.size();
vRip.emplace_back( R"( ) < )" );
vRip.emplace_back( R"(| |)" );
vRip.emplace_back( R"(| |)" );
vRip.emplace_back( R"(| _ |)" );
vRip.emplace_back( R"(|__/ |)" );
iMaxWidth = utf8_width( vRip.back() );
vRip.emplace_back( R"( / `--. |)" );
vRip.emplace_back( R"(| ( )" );
iInfoLine = vRip.size();
vRip.emplace_back( R"(| |)" );
vRip.emplace_back( R"(| |)" );
vRip.emplace_back( R"(| % . |)" );
vRip.emplace_back( R"(| @` %% |)" );
vRip.emplace_back( R"(| %@%@%\ * %`%@%|)" );
vRip.emplace_back( R"(%%@@@.%@%\%% `\ %%.%%@@%@)" );
vRip.emplace_back( R"(@%@@%%%%%@@@@@@%%%%%%%%@@%%@@@%%%@%%@)" );
}

const point iOffset( TERMX > FULL_SCREEN_WIDTH ? ( TERMX - FULL_SCREEN_WIDTH ) / 2 : 0,
TERMY > FULL_SCREEN_HEIGHT ? ( TERMY - FULL_SCREEN_HEIGHT ) / 2 : 0 );

catacurses::window w_rip = catacurses::newwin( FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH,
iOffset );
draw_border( w_rip );

sfx::do_player_death_hurt( get_player_character(), true );
sfx::fade_audio_group( sfx::group::weather, 2000 );
sfx::fade_audio_group( sfx::group::time_of_day, 2000 );
sfx::fade_audio_group( sfx::group::context_themes, 2000 );
sfx::fade_audio_group( sfx::group::fatigue, 2000 );

for( size_t iY = 0; iY < vRip.size(); ++iY ) {
size_t iX = 0;
const char *str = vRip[iY].data();
for( int slen = vRip[iY].size(); slen > 0; ) {
const uint32_t cTemp = UTF8_getch( &str, &slen );
if( cTemp != U' ' ) {
nc_color ncColor = c_light_gray;

if( cTemp == U'%' ) {
ncColor = c_green;

} else if( cTemp == U'_' || cTemp == U'|' ) {
ncColor = c_white;

} else if( cTemp == U'@' ) {
ncColor = c_brown;

} else if( cTemp == U'*' ) {
ncColor = c_red;
}

mvwputch( w_rip, point( iX + FULL_SCREEN_WIDTH / 2 - ( iMaxWidth / 2 ), iY + 1 ), ncColor,
cTemp );
}
iX += mk_wcwidth( cTemp );
}
}

std::string sTemp;

center_print( w_rip, iInfoLine++, c_white, _( "Survived:" ) );

const time_duration survived = calendar::turn - calendar::start_of_game;
const int minutes = to_minutes<int>( survived ) % 60;
const int hours = to_hours<int>( survived ) % 24;
const int days = to_days<int>( survived );

if( days > 0 ) {
// NOLINTNEXTLINE(cata-translate-string-literal)
sTemp = string_format( "%dd %dh %dm", days, hours, minutes );
} else if( hours > 0 ) {
// NOLINTNEXTLINE(cata-translate-string-literal)
sTemp = string_format( "%dh %dm", hours, minutes );
} else {
// NOLINTNEXTLINE(cata-translate-string-literal)
sTemp = string_format( "%dm", minutes );
}

center_print( w_rip, iInfoLine++, c_white, sTemp );

const int iTotalKills = g->get_kill_tracker().monster_kill_count();

sTemp = _( "Kills:" );
mvwprintz( w_rip, point( FULL_SCREEN_WIDTH / 2 - 5, 1 + iInfoLine++ ), c_light_gray,
( sTemp + " " ) );
wprintz( w_rip, c_magenta, "%d", iTotalKills );

sTemp = _( "In memory of:" );
mvwprintz( w_rip, point( FULL_SCREEN_WIDTH / 2 - utf8_width( sTemp ) / 2, iNameLine++ ),
c_light_gray,
sTemp );

sTemp = u.get_name();
mvwprintz( w_rip, point( FULL_SCREEN_WIDTH / 2 - utf8_width( sTemp ) / 2, iNameLine++ ), c_white,
sTemp );

sTemp = _( "Last Words:" );
mvwprintz( w_rip, point( FULL_SCREEN_WIDTH / 2 - utf8_width( sTemp ) / 2, iNameLine++ ),
c_light_gray,
sTemp );

int iStartX = FULL_SCREEN_WIDTH / 2 - ( ( iMaxWidth - 4 ) / 2 );
std::string sLastWords = string_input_popup()
.window( w_rip, point( iStartX, iNameLine ), iStartX + iMaxWidth - 4 - 1 )
.max_length( iMaxWidth - 4 - 1 )
.query_string();
g->death_screen();
const bool is_suicide = g->uquit == QUIT_SUICIDE;
std::chrono::seconds time_since_load =
std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::steady_clock::now() - g->time_of_last_load );
std::chrono::seconds total_time_played = g->time_played_at_last_load + time_since_load;
get_event_bus().send<event_type::game_over>( is_suicide, sLastWords, total_time_played );
get_event_bus().send<event_type::game_over>( total_time_played );
// Struck the save_player_data here to forestall Weirdness
g->move_save_to_graveyard();
g->write_memorial_file( sLastWords );
g->write_memorial_file( g->stats().value_of( event_statistic_last_words )
.get<cata_variant_type::string>() );
get_memorial().clear();
std::vector<std::string> characters = g->list_active_saves();
// remove current player from the active characters list, as they are dead
Expand Down
6 changes: 5 additions & 1 deletion src/event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ std::string enum_to_string<event_type>( event_type data )
case event_type::gains_addiction: return "gains_addiction";
case event_type::gains_mutation: return "gains_mutation";
case event_type::gains_skill_level: return "gains_skill_level";
case event_type::game_avatar_death: return "game_avatar_death";
case event_type::game_avatar_new: return "game_avatar_new";
case event_type::game_load: return "game_load";
case event_type::game_over: return "game_over";
case event_type::game_save: return "game_save";
Expand Down Expand Up @@ -124,7 +126,7 @@ DEFINE_EVENT_HELPER_FIELDS( event_spec_empty )
DEFINE_EVENT_HELPER_FIELDS( event_spec_character )
DEFINE_EVENT_HELPER_FIELDS( event_spec_character_item )

static_assert( static_cast<int>( event_type::num_event_types ) == 87,
static_assert( static_cast<int>( event_type::num_event_types ) == 89,
"This static_assert is a reminder to add a definition below when you add a new "
"event_type. If your event_spec specialization inherits from another struct for "
"its fields definition then you probably don't need a definition here." );
Expand Down Expand Up @@ -165,6 +167,8 @@ DEFINE_EVENT_FIELDS( fuel_tank_explodes )
DEFINE_EVENT_FIELDS( gains_addiction )
DEFINE_EVENT_FIELDS( gains_mutation )
DEFINE_EVENT_FIELDS( gains_skill_level )
DEFINE_EVENT_FIELDS( game_avatar_death )
DEFINE_EVENT_FIELDS( game_avatar_new )
DEFINE_EVENT_FIELDS( game_load )
DEFINE_EVENT_FIELDS( game_over )
DEFINE_EVENT_FIELDS( game_save )
Expand Down
Loading

0 comments on commit 82b6ecb

Please sign in to comment.