Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve radio scanning experience, make it more likely there will be radios in range #59550

Merged
merged 1 commit into from
Jul 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions data/json/snippets/radio.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,40 @@
"USS Eagle of Freedom to all callsigns. Operation Ocean 11 is in effect. Repeat. Operation Ocean 11 is in effect. Sir, this should effectively reach about 150 units, but there is no response from literally anyone in hours. Their coms winked out like candles in the wind. And how do we even secure the port to load anyone in?",
"Seagull 54 to USS Eagle of Freedom. It's as we predicted. Going down on last reserves of fuel, with dropping evacuated unit out of question at that point. This is our last call. Will try emergency landing at …kshssssssk… Don't send us a rescue team, we know the odds. Will be moving east towards the shore, and if we're not there in T minus 3 days, count us dead. Proud to serve the country. Over and out."
]
},
{
"type": "snippet",
"category": "radio_station_desc_noise_0",
"text": [ "It's quite clear." ]
},
{
"type": "snippet",
"category": "radio_station_desc_noise_20",
"text": [ "There's some noise, but you can make it out pretty well." ]
},
{
"type": "snippet",
"category": "radio_station_desc_noise_40",
"text": [ "There's a fair bit of noise, but you can occasionally make it out." ]
},
{
"type": "snippet",
"category": "radio_station_desc_noise_60",
"text": [ "There's a lot of noise, but you can make out something through it." ]
},
{
"type": "snippet",
"category": "radio_station_desc_noise_80",
"text": [ "You can barely make out a message through the noise." ]
},
{
"type": "snippet",
"category": "radio_station_desc_noise_max",
"text": [ "Only the occasional word escapes the static." ]
},
{
"type": "snippet",
"category": "radio_scan_no_stations",
"text": [ "You fiddle with the dial a bit, but there's only noise." ]
}
]
1 change: 1 addition & 0 deletions src/debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ std::string filter_name( debug_filter value )
case DF_MONSTER: return "DF_MONSTER";
case DF_NPC: return "DF_NPC";
case DF_OVERMAP: return "DF_OVERMAP";
case DF_RADIO: return "DF_RADIO";
case DF_RANGED: return "DF_RANGED";
case DF_REQUIREMENTS_MAP: return "DF_REQUIREMENTS_MAP";
case DF_SOUND: return "DF_SOUND";
Expand Down
1 change: 1 addition & 0 deletions src/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ enum debug_filter : int {
DF_MONSTER, // monster generic
DF_NPC, // npc generic
DF_OVERMAP, // overmap generic
DF_RADIO, // radio stuff
DF_RANGED, // ranged generic
DF_REQUIREMENTS_MAP, // activity_item_handler requirements_map()
DF_SOUND, // sound generic
Expand Down
111 changes: 84 additions & 27 deletions src/iuse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2452,34 +2452,67 @@ cata::optional<int> iuse::directional_antenna( Character *p, item *it, bool, con
return it->type->charges_to_use();
}

// 0-100 percent chance of a character in a radio signal being obscured by static
static int radio_static_chance( const radio_tower_reference &tref )
{
constexpr int HALF_RADIO_MIN = RADIO_MIN_STRENGTH / 2;
const int signal_strength = tref.signal_strength;
const int max_strength = tref.tower->strength;
int dist = max_strength - signal_strength;
// For towers whose strength is quite close to the min, make them act as though they are farther away
if( RADIO_MIN_STRENGTH * 1.25 > max_strength ) {
dist += 25;
}
// When we're close enough, there's no noise
if( dist < HALF_RADIO_MIN ) {
return 0;
}
// There's minimal, but increasing noise when quite close to the signal
if( dist < RADIO_MIN_STRENGTH ) {
return lerp( 1, 20, static_cast<float>( dist - HALF_RADIO_MIN ) / HALF_RADIO_MIN );
}
// Otherwise, just a rapid increase until the signal stops
return lerp( 20, 100, static_cast<float>( dist - RADIO_MIN_STRENGTH ) /
( max_strength - RADIO_MIN_STRENGTH ) );
}

cata::optional<int> iuse::radio_on( Character *p, item *it, bool t, const tripoint &pos )
{
if( t ) {
// Normal use
std::string message = _( "Radio: Kssssssssssssh." );
const radio_tower_reference tref = overmap_buffer.find_radio_station( it->frequency );
add_msg_debug( debugmode::DF_RADIO, "Set freq: %d", it->frequency );
if( tref ) {
point_abs_omt dbgpos = project_to<coords::omt>( tref.abs_sm_pos );
add_msg_debug( debugmode::DF_RADIO, "found broadcast (str %d) at (%d %d)",
tref.signal_strength, dbgpos.x(), dbgpos.y() );
const radio_tower *selected_tower = tref.tower;
if( selected_tower->type == radio_type::MESSAGE_BROADCAST ) {
message = selected_tower->message;
} else if( selected_tower->type == radio_type::WEATHER_RADIO ) {
message = weather_forecast( tref.abs_sm_pos );
}

message = obscure_message( message, [&]()->int {
int signal_roll = dice( 10, tref.signal_strength * 3 );
int static_roll = dice( 10, 100 );
if( static_roll > signal_roll )
const city *c = overmap_buffer.closest_city( tripoint_abs_sm( tref.abs_sm_pos, 0 ) ).city;
const std::string cityname = c == nullptr ? "ksssh" : c->name;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this is a onomatopoeia, it should probably be translated.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, my bad.


replace_city_tag( message, cityname );
int static_chance = radio_static_chance( tref );
add_msg_debug( debugmode::DF_RADIO, "Message: '%s' at %d%% noise", message, static_chance );
message = obscure_message( message, [&static_chance]()->int {
if( x_in_y( static_chance, 100 ) )
{
if( static_roll < signal_roll * 1.1 && one_in( 4 ) ) {
// Gradually replace random characters with noise as distance increases
if( one_in( 3 ) && static_chance - rng( 0, 25 ) < 50 ) {
// Replace with random character
return 0;
} else {
return '#';
}
} else
{
return -1;
// Replace with '#'
return '#';
}
// Leave unchanged
return -1;
} );

std::vector<std::string> segments = foldstring( message, RADIO_PER_TURN );
Expand All @@ -2503,27 +2536,51 @@ cata::optional<int> iuse::radio_on( Character *p, item *it, bool t, const tripoi
} );
}

const auto tower_desc = []( const int noise ) {
if( noise == 0 ) {
return SNIPPET.random_from_category( "radio_station_desc_noise_0" )->translated();
} else if( noise <= 20 ) {
return SNIPPET.random_from_category( "radio_station_desc_noise_20" )->translated();
} else if( noise <= 40 ) {
return SNIPPET.random_from_category( "radio_station_desc_noise_40" )->translated();
} else if( noise <= 60 ) {
return SNIPPET.random_from_category( "radio_station_desc_noise_60" )->translated();
} else if( noise <= 80 ) {
return SNIPPET.random_from_category( "radio_station_desc_noise_80" )->translated();
}
return SNIPPET.random_from_category( "radio_station_desc_noise_max" )->translated();
};

switch( ch ) {
case 0: {
const int old_frequency = it->frequency;
const radio_tower *lowest_tower = nullptr;
const radio_tower *lowest_larger_tower = nullptr;
for( radio_tower_reference &tref : overmap_buffer.find_all_radio_stations() ) {
const int new_frequency = tref.tower->frequency;
if( new_frequency == old_frequency ) {
continue;
}
if( new_frequency > old_frequency &&
( lowest_larger_tower == nullptr || new_frequency < lowest_larger_tower->frequency ) ) {
lowest_larger_tower = tref.tower;
} else if( lowest_tower == nullptr || new_frequency < lowest_tower->frequency ) {
lowest_tower = tref.tower;
std::vector<radio_tower_reference> options = overmap_buffer.find_all_radio_stations();
if( options.empty() ) {
popup( SNIPPET.random_from_category( "radio_scan_no_stations" )->translated() );
}
uilist scanlist;
scanlist.title = _( "Select a station" );
scanlist.desc_enabled = true;
add_msg_debug( debugmode::DF_RADIO, "Radio scan:" );
for( size_t i = 0; i < options.size(); ++i ) {
std::string selected_text;
const radio_tower_reference &tref = options[i];
if( it->frequency == tref.tower->frequency ) {
selected_text = pgettext( "radio station", " (selected)" );
}
//~ Selected radio station, %d is a number in sequence (1,2,3...),
//~ %s is ' (selected)' if this is the radio station playing, else nothing
const std::string station_name = string_format( _( "Station %d%s" ), i + 1, selected_text );
const int noise_chance = radio_static_chance( tref );
scanlist.addentry_desc( i, true, MENU_AUTOASSIGN, station_name, tower_desc( noise_chance ) );
const point_abs_omt dbgpos = project_to<coords::omt>( tref.abs_sm_pos );
add_msg_debug( debugmode::DF_RADIO, " %d: %d at (%d %d) str [%d/%d]", i + 1, tref.tower->frequency,
dbgpos.x(), dbgpos.y(), tref.signal_strength, tref.tower->strength );
}
if( lowest_larger_tower != nullptr ) {
it->frequency = lowest_larger_tower->frequency;
} else if( lowest_tower != nullptr ) {
it->frequency = lowest_tower->frequency;
scanlist.query();
const int sel = scanlist.ret;
if( sel >= 0 && static_cast<size_t>( sel ) < options.size() ) {
it->frequency = options[sel].tower->frequency;
break;
}
}
break;
Expand Down
4 changes: 2 additions & 2 deletions src/overmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ enum class radio_type : int {

extern std::map<radio_type, std::string> radio_type_names;

static constexpr int RADIO_MIN_STRENGTH = 80;
static constexpr int RADIO_MAX_STRENGTH = 200;
static constexpr int RADIO_MIN_STRENGTH = 120;
static constexpr int RADIO_MAX_STRENGTH = 360;

struct radio_tower {
// local (to the containing overmap) submap coordinates
Expand Down
3 changes: 3 additions & 0 deletions src/savegame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,8 @@ void overmap::unserialize( std::istream &fin )
jsin.read( new_radio.strength );
} else if( radio_member_name == "message" ) {
jsin.read( new_radio.message );
} else if( radio_member_name == "frequency" ) {
jsin.read( new_radio.frequency );
}
}
radios.push_back( new_radio );
Expand Down Expand Up @@ -1220,6 +1222,7 @@ void overmap::serialize( std::ostream &fout ) const
json.member( "strength", i.strength );
json.member( "type", radio_type_names[i.type] );
json.member( "message", i.message );
json.member( "frequency", i.frequency );
json.end_object();
}
json.end_array();
Expand Down