diff --git a/src/action.cpp b/src/action.cpp index afb969de79792..087c85bd45915 100644 --- a/src/action.cpp +++ b/src/action.cpp @@ -618,7 +618,7 @@ bool can_move_vertical_at( const tripoint &p, int movez ) if( movez == -1 ) { return !g->u.is_underwater() && !g->u.worn_with_flag( flag_FLOTATION ); } else { - return g->u.swim_speed() < 500 || g->u.is_wearing( "swim_fins" ); + return g->u.swim_speed() < 500 || g->u.is_wearing( itype_id( "swim_fins" ) ); } } diff --git a/src/activity_actor.cpp b/src/activity_actor.cpp index 24abca877ad25..7c62943061812 100644 --- a/src/activity_actor.cpp +++ b/src/activity_actor.cpp @@ -32,6 +32,9 @@ static const bionic_id bio_fingerhack( "bio_fingerhack" ); +static const itype_id itype_bone_human( "bone_human" ); +static const itype_id itype_electrohack( "electrohack" ); + static const skill_id skill_computer( "computer" ); static const trait_id trait_ILLITERATE( "ILLITERATE" ); @@ -76,7 +79,7 @@ void dig_activity_actor::finish( player_activity &act, Character &who ) g->m.furn_set( location, f_coffin_o ); who.add_msg_if_player( m_warning, _( "Something crawls out of the coffin!" ) ); } else { - g->m.spawn_item( location, "bone_human", rng( 5, 15 ) ); + g->m.spawn_item( location, itype_bone_human, rng( 5, 15 ) ); g->m.furn_set( location, f_coffin_c ); } std::vector dropped = g->m.place_items( "allclothes", 50, location, location, false, @@ -244,7 +247,7 @@ static hack_result hack_attempt( Character &who ) if( who.has_trait( trait_ILLITERATE ) ) { return HACK_UNABLE; } - const bool using_electrohack = who.has_charges( "electrohack", 25 ) && + const bool using_electrohack = who.has_charges( itype_electrohack, 25 ) && query_yn( _( "Use electrohack?" ) ); const bool using_fingerhack = !using_electrohack && who.has_bionic( bio_fingerhack ) && who.get_power_level() > 24_kJ && query_yn( _( "Use fingerhack?" ) ); @@ -261,7 +264,7 @@ static hack_result hack_attempt( Character &who ) if( using_fingerhack ) { who.mod_power_level( -25_kJ ); } else { - who.use_charges( "electrohack", 25 ); + who.use_charges( itype_electrohack, 25 ); } // only skilled supergenius never cause short circuits, but the odds are low for people @@ -273,13 +276,13 @@ static hack_result hack_attempt( Character &who ) if( using_fingerhack ) { who.mod_power_level( -25_kJ ); } else { - who.use_charges( "electrohack", 25 ); + who.use_charges( itype_electrohack, 25 ); } if( success <= -5 ) { if( using_electrohack ) { who.add_msg_if_player( m_bad, _( "Your electrohack is ruined!" ) ); - who.use_amount( "electrohack", 1 ); + who.use_amount( itype_electrohack, 1 ); } else { who.add_msg_if_player( m_bad, _( "Your power is drained!" ) ); who.mod_power_level( units::from_kilojoule( -rng( 25, diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index 1bbc5791bd6e3..7a6dd3e0f0fb3 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -208,6 +208,33 @@ static const efftype_id effect_sleep( "sleep" ); static const efftype_id effect_tied( "tied" ); static const efftype_id effect_under_op( "under_operation" ); +static const itype_id itype_2x4( "2x4" ); +static const itype_id itype_animal( "animal" ); +static const itype_id itype_battery( "battery" ); +static const itype_id itype_burnt_out_bionic( "burnt_out_bionic" ); +static const itype_id itype_chain( "chain" ); +static const itype_id itype_grapnel( "grapnel" ); +static const itype_id itype_hd_tow_cable( "hd_tow_cable" ); +static const itype_id itype_log( "log" ); +static const itype_id itype_mind_scan_robofac( "mind_scan_robofac" ); +static const itype_id itype_muscle( "muscle" ); +static const itype_id itype_nail( "nail" ); +static const itype_id itype_pipe( "pipe" ); +static const itype_id itype_rope_30( "rope_30" ); +static const itype_id itype_rope_makeshift_30( "rope_makeshift_30" ); +static const itype_id itype_ruined_chunks( "ruined_chunks" ); +static const itype_id itype_scrap( "scrap" ); +static const itype_id itype_sheet_metal( "sheet_metal" ); +static const itype_id itype_spike( "spike" ); +static const itype_id itype_splinter( "splinter" ); +static const itype_id itype_stick_long( "stick_long" ); +static const itype_id itype_steel_chunk( "steel_chunk" ); +static const itype_id itype_steel_plate( "steel_plate" ); +static const itype_id itype_vine_30( "vine_30" ); +static const itype_id itype_wire( "wire" ); +static const itype_id itype_welder( "welder" ); +static const itype_id itype_wool_staple( "wool_staple" ); + static const zone_type_id zone_type_FARM_PLOT( "FARM_PLOT" ); static const skill_id skill_computer( "computer" ); @@ -472,15 +499,15 @@ static bool check_butcher_cbm( const int roll ) return !failed; } -static void butcher_cbm_item( const std::string &what, const tripoint &pos, +static void butcher_cbm_item( const itype_id &what, const tripoint &pos, const time_point &age, const int roll, const std::vector &flags, const std::vector &faults ) { if( roll < 0 ) { return; } - if( item::find_type( itype_id( what ) )->bionic ) { - item cbm( check_butcher_cbm( roll ) ? what : "burnt_out_bionic", age ); + if( item::find_type( what )->bionic ) { + item cbm( check_butcher_cbm( roll ) ? what : itype_burnt_out_bionic, age ); for( const std::string &flg : flags ) { cbm.set_flag( flg ); } @@ -527,7 +554,7 @@ static void butcher_cbm_group( const std::string &group, const tripoint &pos, } } else { //There is a burnt out CBM - item cbm( "burnt_out_bionic", age ); + item cbm( itype_burnt_out_bionic, age ); for( const std::string &flg : flags ) { cbm.set_flag( flg ); } @@ -594,9 +621,12 @@ static void set_up_butchery( player_activity &act, player &u, butcher_type actio } // workshop butchery (full) prequisites if( action == BUTCHER_FULL ) { - const bool has_rope = u.has_amount( "rope_30", 1 ) || u.has_amount( "rope_makeshift_30", 1 ) || - u.has_amount( "hd_tow_cable", 1 ) || - u.has_amount( "vine_30", 1 ) || u.has_amount( "grapnel", 1 ) || u.has_amount( "chain", 1 ); + const bool has_rope = u.has_amount( itype_rope_30, 1 ) || + u.has_amount( itype_rope_makeshift_30, 1 ) || + u.has_amount( itype_hd_tow_cable, 1 ) || + u.has_amount( itype_vine_30, 1 ) || + u.has_amount( itype_grapnel, 1 ) || + u.has_amount( itype_chain, 1 ); const bool big_corpse = corpse.size >= MS_MEDIUM; if( big_corpse ) { @@ -878,9 +908,11 @@ static void butchery_drops_harvest( item *corpse_item, const mtype &mt, player & roll = std::max( corpse_damage_effect( roll, entry.type, corpse_item->damage_level( 4 ) ), entry.base_num.first ); } + itype_id drop_id = itype_id::NULL_ID(); const itype *drop = nullptr; if( entry.type != "bionic_group" ) { - drop = item::find_type( entry.drop ); + drop_id = itype_id( entry.drop ); + drop = item::find_type( drop_id ); } // BIONIC handling - no code for DISSECT to let the bionic drop fall through @@ -928,7 +960,7 @@ static void butchery_drops_harvest( item *corpse_item, const mtype &mt, player & roll = std::min( entry.max, roll ); add_msg( m_debug, _( "Roll penalty for corpse damage = %s" ), 0 - corpse_item->damage_level( 4 ) ); if( entry.type == "bionic" ) { - butcher_cbm_item( entry.drop, p.pos(), calendar::turn, roll, entry.flags, entry.faults ); + butcher_cbm_item( drop_id, p.pos(), calendar::turn, roll, entry.flags, entry.faults ); } else if( entry.type == "bionic_group" ) { butcher_cbm_group( entry.drop, p.pos(), calendar::turn, roll, entry.flags, entry.faults ); } @@ -1028,9 +1060,9 @@ static void butchery_drops_harvest( item *corpse_item, const mtype &mt, player & roll *= roll_drops(); monster_weight_remaining -= roll; roll = std::ceil( static_cast( roll ) / - to_gram( item::find_type( entry.drop )->weight ) ); + to_gram( drop->weight ) ); } else { - monster_weight_remaining -= roll * to_gram( ( item::find_type( entry.drop ) )->weight ); + monster_weight_remaining -= roll * to_gram( drop->weight ); } if( roll <= 0 ) { @@ -1124,9 +1156,9 @@ static void butchery_drops_harvest( item *corpse_item, const mtype &mt, player & } } const int item_charges = monster_weight_remaining / to_gram( ( - item::find_type( "ruined_chunks" ) )->weight ); + item::find_type( itype_ruined_chunks ) )->weight ); if( item_charges > 0 ) { - item ruined_parts( "ruined_chunks", calendar::turn, item_charges ); + item ruined_parts( itype_ruined_chunks, calendar::turn, item_charges ); ruined_parts.set_mtype( &mt ); ruined_parts.set_item_temperature( 0.00001 * corpse_item->temperature ); ruined_parts.set_rot( corpse_item->get_rot() ); @@ -1291,7 +1323,7 @@ void activity_handlers::butcher_finish( player_activity *act, player *p ) corpse->nname() ); g->m.add_item_or_charges( p->pos(), *content ); } else if( content->is_bionic() ) { - g->m.spawn_item( p->pos(), "burnt_out_bionic", 1, 0, calendar::turn ); + g->m.spawn_item( p->pos(), itype_burnt_out_bionic, 1, 0, calendar::turn ); } } } @@ -1458,7 +1490,7 @@ void activity_handlers::shear_finish( player_activity *act, player *p ) } // 22 wool staples corresponds to an average wool-producing sheep yield of 10 lbs or so for( int i = 0; i != 22; ++i ) { - item wool_staple( "wool_staple", calendar::turn ); + item wool_staple( itype_wool_staple, calendar::turn ); g->m.add_item_or_charges( p->pos(), wool_staple ); } source_mon->add_effect( effect_sheared, calendar::season_length() ); @@ -2068,7 +2100,8 @@ void activity_handlers::reload_finish( player_activity *act, player *p ) } } if( reloadable.type->gun->reload_noise_volume > 0 ) { - sfx::play_variant_sound( "reload", reloadable.typeId(), sfx::get_heard_volume( p->pos() ) ); + sfx::play_variant_sound( "reload", reloadable.typeId().str(), + sfx::get_heard_volume( p->pos() ) ); sounds::ambient_sound( p->pos(), reloadable.type->gun->reload_noise_volume, sounds::sound_t::activity, reloadable.type->gun->reload_noise ); } @@ -2261,7 +2294,7 @@ void activity_handlers::hand_crank_do_turn( player_activity *act, player *p ) if( calendar::once_every( 144_seconds ) ) { p->mod_fatigue( 1 ); if( hand_crank_item.ammo_capacity() > hand_crank_item.ammo_remaining() ) { - hand_crank_item.ammo_set( "battery", hand_crank_item.ammo_remaining() + 1 ); + hand_crank_item.ammo_set( itype_battery, hand_crank_item.ammo_remaining() + 1 ); } else { act->moves_left = 0; add_msg( m_info, _( "You've charged the battery completely." ) ); @@ -2281,8 +2314,7 @@ void activity_handlers::vibe_do_turn( player_activity *act, player *p ) //Deduct 1 battery charge for every minute in use, or vibrator is much less effective item &vibrator_item = *act->targets.front(); - if( ( p->is_wearing( "rebreather" ) ) || ( p->is_wearing( "rebreather_xl" ) ) || - ( p->is_wearing( "mask_h20survivor" ) ) ) { + if( p->encumb( bp_mouth ) >= 30 ) { act->moves_left = 0; add_msg( m_bad, _( "You have trouble breathing, and stop." ) ); } @@ -2333,12 +2365,14 @@ void activity_handlers::start_engines_finish( player_activity *act, player *p ) for( size_t e = 0; e < veh->engines.size(); ++e ) { if( veh->is_engine_on( e ) ) { attempted++; - if( !veh->is_engine_type( e, "muscle" ) && !veh->is_engine_type( e, "animal" ) ) { + if( !veh->is_engine_type( e, itype_muscle ) && + !veh->is_engine_type( e, itype_animal ) ) { non_muscle_attempted++; } if( veh->start_engine( e ) ) { started++; - if( !veh->is_engine_type( e, "muscle" ) && !veh->is_engine_type( e, "animal" ) ) { + if( !veh->is_engine_type( e, itype_muscle ) && + !veh->is_engine_type( e, itype_animal ) ) { non_muscle_started++; } else { non_combustion_started++; @@ -2410,44 +2444,44 @@ void activity_handlers::oxytorch_finish( player_activity *act, player *p ) if( g->m.furn( pos ) == f_rack ) { g->m.furn_set( pos, f_null ); - g->m.spawn_item( p->pos(), "steel_chunk", rng( 2, 6 ) ); + g->m.spawn_item( p->pos(), itype_steel_chunk, rng( 2, 6 ) ); } else if( ter == t_chainfence || ter == t_chaingate_c || ter == t_chaingate_l ) { g->m.ter_set( pos, t_dirt ); - g->m.spawn_item( pos, "pipe", rng( 1, 4 ) ); - g->m.spawn_item( pos, "wire", rng( 4, 16 ) ); + g->m.spawn_item( pos, itype_pipe, rng( 1, 4 ) ); + g->m.spawn_item( pos, itype_wire, rng( 4, 16 ) ); } else if( ter == t_chainfence_posts ) { g->m.ter_set( pos, t_dirt ); - g->m.spawn_item( pos, "pipe", rng( 1, 4 ) ); + g->m.spawn_item( pos, itype_pipe, rng( 1, 4 ) ); } else if( ter == t_door_metal_locked || ter == t_door_metal_c || ter == t_door_bar_c || ter == t_door_bar_locked || ter == t_door_metal_pickable ) { g->m.ter_set( pos, t_mdoor_frame ); - g->m.spawn_item( pos, "steel_plate", rng( 0, 1 ) ); - g->m.spawn_item( pos, "steel_chunk", rng( 3, 8 ) ); + g->m.spawn_item( pos, itype_steel_plate, rng( 0, 1 ) ); + g->m.spawn_item( pos, itype_steel_chunk, rng( 3, 8 ) ); } else if( ter == t_window_enhanced || ter == t_window_enhanced_noglass ) { g->m.ter_set( pos, t_window_empty ); - g->m.spawn_item( pos, "steel_plate", rng( 0, 1 ) ); - g->m.spawn_item( pos, "sheet_metal", rng( 1, 3 ) ); + g->m.spawn_item( pos, itype_steel_plate, rng( 0, 1 ) ); + g->m.spawn_item( pos, itype_sheet_metal, rng( 1, 3 ) ); } else if( ter == t_reb_cage ) { g->m.ter_set( pos, t_pit ); - g->m.spawn_item( pos, "spike", rng( 1, 19 ) ); - g->m.spawn_item( pos, "scrap", rng( 1, 8 ) ); + g->m.spawn_item( pos, itype_spike, rng( 1, 19 ) ); + g->m.spawn_item( pos, itype_scrap, rng( 1, 8 ) ); } else if( ter == t_bars ) { if( g->m.ter( pos + point_east ) == t_sewage || g->m.ter( pos + point_south ) == t_sewage || g->m.ter( pos + point_west ) == t_sewage || g->m.ter( pos + point_north ) == t_sewage ) { g->m.ter_set( pos, t_sewage ); - g->m.spawn_item( p->pos(), "pipe", rng( 1, 2 ) ); + g->m.spawn_item( p->pos(), itype_pipe, rng( 1, 2 ) ); } else { g->m.ter_set( pos, t_floor ); - g->m.spawn_item( p->pos(), "pipe", rng( 1, 2 ) ); + g->m.spawn_item( p->pos(), itype_pipe, rng( 1, 2 ) ); } } else if( ter == t_window_bars_alarm ) { g->m.ter_set( pos, t_window_alarm ); - g->m.spawn_item( p->pos(), "pipe", rng( 1, 2 ) ); + g->m.spawn_item( p->pos(), itype_pipe, rng( 1, 2 ) ); } else if( ter == t_window_bars ) { g->m.ter_set( pos, t_window_empty ); - g->m.spawn_item( p->pos(), "pipe", rng( 1, 2 ) ); + g->m.spawn_item( p->pos(), itype_pipe, rng( 1, 2 ) ); } } @@ -2585,7 +2619,7 @@ struct weldrig_hack { weldrig_hack() : veh( nullptr ) , part( -1 ) - , pseudo( "welder", calendar::turn ) + , pseudo( itype_welder, calendar::turn ) { } bool init( const player_activity &act ) { @@ -2606,7 +2640,7 @@ struct weldrig_hack { item &get_item() { if( veh != nullptr && part >= 0 ) { - pseudo.charges = veh->drain( "battery", 1000 - pseudo.charges ); + pseudo.charges = veh->drain( itype_battery, 1000 - pseudo.charges ); return pseudo; } @@ -2799,7 +2833,7 @@ void activity_handlers::heat_item_finish( player_activity *act, player *p ) } item *const food = heat->get_food(); if( food == nullptr ) { - debugmsg( "item %s is not food", heat->typeId() ); + debugmsg( "item %s is not food", heat->typeId().str() ); return; } item &target = *food; @@ -2891,7 +2925,7 @@ void activity_handlers::gunmod_add_finish( player_activity *act, player *p ) const int risk = act->values[2]; // any tool charges used during installation - const std::string tool = act->name; + const itype_id tool( act->name ); const int qty = act->values[3]; if( !gun.is_gunmod_compatible( mod ).success() ) { @@ -2899,7 +2933,7 @@ void activity_handlers::gunmod_add_finish( player_activity *act, player *p ) return; } - if( !tool.empty() && qty > 0 ) { + if( !tool.is_empty() && qty > 0 ) { p->use_charges( tool, qty ); } @@ -3587,7 +3621,7 @@ void activity_handlers::churn_finish( player_activity *act, player *p ) void activity_handlers::plant_seed_finish( player_activity *act, player *p ) { tripoint examp = g->m.getlocal( act->placement ); - const std::string seed_id = act->str_values[0]; + const itype_id seed_id( act->str_values[0] ); std::list used_seed; if( item::count_by_charges( seed_id ) ) { used_seed = p->use_charges( seed_id, 1 ); @@ -3876,45 +3910,45 @@ void activity_handlers::hacksaw_finish( player_activity *act, player *p ) if( g->m.furn( pos ) == f_rack ) { g->m.furn_set( pos, f_null ); - g->m.spawn_item( p->pos(), "pipe", rng( 1, 3 ) ); - g->m.spawn_item( p->pos(), "steel_chunk" ); + g->m.spawn_item( p->pos(), itype_pipe, rng( 1, 3 ) ); + g->m.spawn_item( p->pos(), itype_steel_chunk ); } else if( ter == t_chainfence || ter == t_chaingate_c || ter == t_chaingate_l ) { g->m.ter_set( pos, t_dirt ); - g->m.spawn_item( p->pos(), "pipe", 6 ); - g->m.spawn_item( p->pos(), "wire", 20 ); + g->m.spawn_item( p->pos(), itype_pipe, 6 ); + g->m.spawn_item( p->pos(), itype_wire, 20 ); } else if( ter == t_chainfence_posts ) { g->m.ter_set( pos, t_dirt ); - g->m.spawn_item( p->pos(), "pipe", 6 ); + g->m.spawn_item( p->pos(), itype_pipe, 6 ); } else if( ter == t_window_bars_alarm ) { g->m.ter_set( pos, t_window_alarm ); - g->m.spawn_item( p->pos(), "pipe", 6 ); + g->m.spawn_item( p->pos(), itype_pipe, 6 ); } else if( ter == t_window_bars ) { g->m.ter_set( pos, t_window_empty ); - g->m.spawn_item( p->pos(), "pipe", 6 ); + g->m.spawn_item( p->pos(), itype_pipe, 6 ); } else if( ter == t_window_enhanced ) { g->m.ter_set( pos, t_window_reinforced ); - g->m.spawn_item( p->pos(), "spike", rng( 1, 4 ) ); + g->m.spawn_item( p->pos(), itype_spike, rng( 1, 4 ) ); } else if( ter == t_window_enhanced_noglass ) { g->m.ter_set( pos, t_window_reinforced_noglass ); - g->m.spawn_item( p->pos(), "spike", rng( 1, 4 ) ); + g->m.spawn_item( p->pos(), itype_spike, rng( 1, 4 ) ); } else if( ter == t_reb_cage ) { g->m.ter_set( pos, t_pit ); - g->m.spawn_item( p->pos(), "spike", 19 ); - g->m.spawn_item( p->pos(), "scrap", 8 ); + g->m.spawn_item( p->pos(), itype_spike, 19 ); + g->m.spawn_item( p->pos(), itype_scrap, 8 ); } else if( ter == t_bars ) { if( g->m.ter( pos + point_east ) == t_sewage || g->m.ter( pos + point_south ) == t_sewage || g->m.ter( pos + point_west ) == t_sewage || g->m.ter( pos + point_north ) == t_sewage ) { g->m.ter_set( pos, t_sewage ); - g->m.spawn_item( p->pos(), "pipe", 3 ); + g->m.spawn_item( p->pos(), itype_pipe, 3 ); } else { g->m.ter_set( pos, t_floor ); - g->m.spawn_item( p->pos(), "pipe", 3 ); + g->m.spawn_item( p->pos(), itype_pipe, 3 ); } } else if( ter == t_door_bar_c || ter == t_door_bar_locked ) { g->m.ter_set( pos, t_mdoor_frame ); - g->m.spawn_item( p->pos(), "pipe", 12 ); + g->m.spawn_item( p->pos(), itype_pipe, 12 ); } p->mod_stored_nutr( 5 ); @@ -3974,8 +4008,8 @@ void activity_handlers::pry_nails_finish( player_activity *act, player *p ) p->add_msg_if_player( _( "You pry the boards from the door." ) ); } p->practice( skill_fabrication, 1, 1 ); - g->m.spawn_item( p->pos(), "nail", 0, nails ); - g->m.spawn_item( p->pos(), "2x4", boards ); + g->m.spawn_item( p->pos(), itype_nail, 0, nails ); + g->m.spawn_item( p->pos(), itype_2x4, boards ); g->m.ter_set( pnt, newter ); act->set_to_null(); } @@ -4063,17 +4097,17 @@ void activity_handlers::chop_logs_finish( player_activity *act, player *p ) splint_quan = 0; } for( int i = 0; i != log_quan; ++i ) { - item obj( "log", calendar::turn ); + item obj( itype_log, calendar::turn ); obj.set_var( "activity_var", p->name ); g->m.add_item_or_charges( pos, obj ); } for( int i = 0; i != stick_quan; ++i ) { - item obj( "stick_long", calendar::turn ); + item obj( itype_stick_long, calendar::turn ); obj.set_var( "activity_var", p->name ); g->m.add_item_or_charges( pos, obj ); } for( int i = 0; i != splint_quan; ++i ) { - item obj( "splinter", calendar::turn ); + item obj( itype_splinter, calendar::turn ); obj.set_var( "activity_var", p->name ); g->m.add_item_or_charges( pos, obj ); } @@ -4098,11 +4132,11 @@ void activity_handlers::chop_planks_finish( player_activity *act, player *p ) planks = std::min( planks, max_planks ); if( planks > 0 ) { - g->m.spawn_item( g->m.getlocal( act->placement ), "2x4", planks, 0, calendar::turn ); + g->m.spawn_item( g->m.getlocal( act->placement ), itype_2x4, planks, 0, calendar::turn ); p->add_msg_if_player( m_good, _( "You produce %d planks." ), planks ); } if( scraps > 0 ) { - g->m.spawn_item( g->m.getlocal( act->placement ), "splinter", scraps, 0, calendar::turn ); + g->m.spawn_item( g->m.getlocal( act->placement ), itype_splinter, scraps, 0, calendar::turn ); p->add_msg_if_player( m_good, _( "You produce %d splinters." ), scraps ); } if( planks < max_planks / 2 ) { @@ -4311,19 +4345,19 @@ void activity_handlers::fertilize_plot_do_turn( player_activity *act, player *p { act->str_values.push_back( "" ); } - fertilizer = act->str_values[0]; + fertilizer = itype_id( act->str_values[0] ); /* If unspecified, or if we're out of what we used before, ask */ - if( ask_user && ( fertilizer.empty() || !p->has_charges( fertilizer, 1 ) ) ) + if( ask_user && ( fertilizer.is_empty() || !p->has_charges( fertilizer, 1 ) ) ) { fertilizer = iexamine::choose_fertilizer( *p, "plant", false /* Don't confirm action with player */ ); - act->str_values[0] = fertilizer; + act->str_values[0] = fertilizer.str(); } }; auto have_fertilizer = [&]() { - return !fertilizer.empty() && p->has_charges( fertilizer, 1 ); + return !fertilizer.is_empty() && p->has_charges( fertilizer, 1 ); }; const auto reject_tile = [&]( const tripoint & tile ) { @@ -4692,5 +4726,5 @@ void activity_handlers::mind_splicer_finish( player_activity *act, player *p ) p->add_msg_if_player( m_info, _( "…you finally find the memory banks." ) ); p->add_msg_if_player( m_info, _( "The kit makes a copy of the data inside the bionic." ) ); data_card.contents.clear_items(); - data_card.put_in( item( "mind_scan_robofac" ), item_pocket::pocket_type::SOFTWARE ); + data_card.put_in( item( itype_mind_scan_robofac ), item_pocket::pocket_type::SOFTWARE ); } diff --git a/src/activity_item_handling.cpp b/src/activity_item_handling.cpp index 3b204bc90d4b3..ced8479c030ca 100644 --- a/src/activity_item_handling.cpp +++ b/src/activity_item_handling.cpp @@ -91,6 +91,15 @@ static const activity_id ACT_VEHICLE_REPAIR( "ACT_VEHICLE_REPAIR" ); static const efftype_id effect_pet( "pet" ); static const efftype_id effect_nausea( "nausea" ); +static const itype_id itype_battery( "battery" ); +static const itype_id itype_detergent( "detergent" ); +static const itype_id itype_log( "log" ); +static const itype_id itype_soap( "soap" ); +static const itype_id itype_soldering_iron( "soldering_iron" ); +static const itype_id itype_water( "water" ); +static const itype_id itype_water_clean( "water_clean" ); +static const itype_id itype_welder( "welder" ); + static const trap_str_id tr_firewood_source( "tr_firewood_source" ); static const trap_str_id tr_unfinished_construction( "tr_unfinished_construction" ); @@ -564,14 +573,14 @@ void activity_handlers::washing_finish( player_activity *act, player *p ) return is_crafting_component( it ) && ( !it.count_by_charges() || it.made_of( LIQUID ) ); }; const inventory &crafting_inv = p->crafting_inventory(); - if( !crafting_inv.has_charges( "water", required.water, is_liquid_crafting_component ) && - !crafting_inv.has_charges( "water_clean", required.water, is_liquid_crafting_component ) ) { + if( !crafting_inv.has_charges( itype_water, required.water, is_liquid_crafting_component ) && + !crafting_inv.has_charges( itype_water_clean, required.water, is_liquid_crafting_component ) ) { p->add_msg_if_player( _( "You need %1$i charges of water or clean water to wash these items." ), required.water ); act->set_to_null(); return; - } else if( !crafting_inv.has_charges( "soap", required.cleanser ) && - !crafting_inv.has_charges( "detergent", required.cleanser ) ) { + } else if( !crafting_inv.has_charges( itype_soap, required.cleanser ) && + !crafting_inv.has_charges( itype_detergent, required.cleanser ) ) { p->add_msg_if_player( _( "You need %1$i charges of cleansing agent to wash these items." ), required.cleanser ); act->set_to_null(); @@ -585,13 +594,13 @@ void activity_handlers::washing_finish( player_activity *act, player *p ) } std::vector comps; - comps.push_back( item_comp( "water", required.water ) ); - comps.push_back( item_comp( "water_clean", required.water ) ); + comps.push_back( item_comp( itype_water, required.water ) ); + comps.push_back( item_comp( itype_water_clean, required.water ) ); p->consume_items( comps, 1, is_liquid_crafting_component ); std::vector comps1; - comps1.push_back( item_comp( "soap", required.cleanser ) ); - comps1.push_back( item_comp( "detergent", required.cleanser ) ); + comps1.push_back( item_comp( itype_soap, required.cleanser ) ); + comps1.push_back( item_comp( itype_detergent, required.cleanser ) ); p->consume_items( comps1 ); p->add_msg_if_player( m_good, _( "You washed your items." ) ); @@ -1048,12 +1057,12 @@ static bool are_requirements_nearby( const std::vector &loot_spots, vehicle &veh = vp->vehicle(); const cata::optional weldpart = vp.part_with_feature( "WELDRIG", true ); if( weldpart ) { - item welder( "welder", 0 ); - welder.charges = veh.fuel_left( "battery", true ); + item welder( itype_welder, 0 ); + welder.charges = veh.fuel_left( itype_battery, true ); welder.item_tags.insert( "PSEUDO" ); temp_inv.add_item( welder ); - item soldering_iron( "soldering_iron", 0 ); - soldering_iron.charges = veh.fuel_left( "battery", true ); + item soldering_iron( itype_soldering_iron, 0 ); + soldering_iron.charges = veh.fuel_left( itype_battery, true ); soldering_iron.item_tags.insert( "PSEUDO" ); temp_inv.add_item( soldering_iron ); } @@ -1293,7 +1302,7 @@ static activity_reason_info can_do_activity_there( const activity_id &act, playe if( act == ACT_MULTIPLE_CHOP_PLANKS ) { //are there even any logs there? for( auto &i : g->m.i_at( src_loc ) ) { - if( i.typeId() == "log" ) { + if( i.typeId() == itype_log ) { // do we have an axe? if( p.has_quality( qual_AXE, 1 ) ) { return activity_reason_info::ok( do_activity_reason::NEEDS_CHOPPING ); @@ -1357,10 +1366,10 @@ static activity_reason_info can_do_activity_there( const activity_id &act, playe } else { // do we have the required seed on our person? const plot_options &options = dynamic_cast( zone.get_options() ); - const std::string seed = options.get_seed(); + const itype_id seed = options.get_seed(); // If its a farm zone with no specified seed, and we've checked for tilling and harvesting. // then it means no further work can be done here - if( seed.empty() ) { + if( seed.is_empty() ) { return activity_reason_info::fail( do_activity_reason::ALREADY_DONE ); } std::vector seed_inv = p.items_with( []( const item & itm ) { @@ -1686,8 +1695,8 @@ static std::vector> requirements_map( player } } for( const std::tuple &elem : final_map ) { - add_msg( m_debug, "%s is fetching %s from x: %d y: %d ", p.disp_name(), std::get<1>( elem ), - std::get<0>( elem ).x, std::get<0>( elem ).y ); + add_msg( m_debug, "%s is fetching %s from x: %d y: %d ", p.disp_name(), + std::get<1>( elem ).str(), std::get<0>( elem ).x, std::get<0>( elem ).y ); } return final_map; } @@ -1903,7 +1912,7 @@ static bool chop_plank_activity( player &p, const tripoint &src_loc ) p.consume_charges( *best_qual, best_qual->type->charges_to_use() ); } for( auto &i : g->m.i_at( src_loc ) ) { - if( i.typeId() == "log" ) { + if( i.typeId() == itype_log ) { g->m.i_rem( src_loc, &i ); int moves = to_moves( 20_minutes ); p.add_msg_if_player( _( "You cut the log into planks." ) ); @@ -2637,7 +2646,8 @@ static bool generic_multi_activity_do( player &p, const activity_id &act_id, std::vector zones = mgr.get_zones( zone_type_FARM_PLOT, g->m.getabs( src_loc ) ); for( const zone_data &zone : zones ) { - const std::string seed = dynamic_cast( zone.get_options() ).get_seed(); + const itype_id seed = + dynamic_cast( zone.get_options() ).get_seed(); std::vector seed_inv = p.items_with( [seed]( const item & itm ) { return itm.typeId() == itype_id( seed ); } ); diff --git a/src/advanced_inv_area.cpp b/src/advanced_inv_area.cpp index 9756d74b6002b..ba2df0e992f44 100644 --- a/src/advanced_inv_area.cpp +++ b/src/advanced_inv_area.cpp @@ -329,14 +329,14 @@ void advanced_inv_area::set_container( const advanced_inv_listitem *advitem ) uistate.adv_inv_container_index = advitem->idx; uistate.adv_inv_container_type = it->typeId(); uistate.adv_inv_container_content_type = !it->is_container_empty() ? - it->contents.legacy_front().typeId() : "null"; + it->contents.legacy_front().typeId() : itype_id::NULL_ID(); set_container_position(); } else { uistate.adv_inv_container_location = -1; uistate.adv_inv_container_index = 0; uistate.adv_inv_container_in_vehicle = false; - uistate.adv_inv_container_type = "null"; - uistate.adv_inv_container_content_type = "null"; + uistate.adv_inv_container_type = itype_id::NULL_ID(); + uistate.adv_inv_container_content_type = itype_id::NULL_ID(); } } @@ -345,7 +345,7 @@ bool advanced_inv_area::is_container_valid( const item *it ) const if( it != nullptr ) { if( it->typeId() == uistate.adv_inv_container_type ) { if( it->is_container_empty() ) { - if( uistate.adv_inv_container_content_type == "null" ) { + if( uistate.adv_inv_container_content_type.is_null() ) { return true; } } else { diff --git a/src/advanced_inv_listitem.h b/src/advanced_inv_listitem.h index 856d6004affd6..a815fe839d276 100644 --- a/src/advanced_inv_listitem.h +++ b/src/advanced_inv_listitem.h @@ -5,6 +5,7 @@ #include #include +#include "type_id.h" #include "units.h" // see item_factory.h @@ -21,7 +22,6 @@ enum aim_location : char; class advanced_inv_listitem { public: - using itype_id = std::string; /** * Index of the item in the itemstack. */ diff --git a/src/ammo.cpp b/src/ammo.cpp index a8d55091c4601..8ce5c34df0987 100644 --- a/src/ammo.cpp +++ b/src/ammo.cpp @@ -9,6 +9,8 @@ #include "string_id.h" #include "type_id.h" +static const itype_id itype_UPS( "UPS" ); + namespace { using ammo_map_t = std::unordered_map; @@ -24,7 +26,7 @@ void ammunition_type::load_ammunition_type( const JsonObject &jsobj ) { ammunition_type &res = all_ammunition_types()[ ammotype( jsobj.get_string( "id" ) ) ]; res.name_ = jsobj.get_string( "name" ); - res.default_ammotype_ = jsobj.get_string( "default" ); + jsobj.read( "default", res.default_ammotype_, true ); } /** @relates string_id */ @@ -64,11 +66,11 @@ void ammunition_type::check_consistency() const auto &at = ammo.second.default_ammotype_; // TODO: these ammo types should probably not have default ammo at all. - if( at == "UPS" || at == "components" || at == "thrown" ) { + if( at == itype_UPS || at.str() == "components" || at.str() == "thrown" ) { continue; } - if( !at.empty() && !item::type_is_defined( at ) ) { + if( !at.is_empty() && !item::type_is_defined( at ) ) { debugmsg( "ammo type %s has invalid default ammo %s", id.c_str(), at.c_str() ); } } diff --git a/src/ammo.h b/src/ammo.h index f159354b07730..6adbc6a3583f4 100644 --- a/src/ammo.h +++ b/src/ammo.h @@ -5,9 +5,9 @@ #include #include -class JsonObject; +#include"type_id.h" -using itype_id = std::string; +class JsonObject; class ammunition_type { diff --git a/src/artifact.cpp b/src/artifact.cpp index 9b4658f15c658..9658a1f7c10c0 100644 --- a/src/artifact.cpp +++ b/src/artifact.cpp @@ -673,7 +673,7 @@ void it_artifact_armor::create_name( const std::string &type ) name = no_translation( artifact_name( type ) ); } -std::string new_artifact() +itype_id new_artifact() { if( one_in( 2 ) ) { // Generate a "tool" artifact @@ -920,7 +920,7 @@ std::string new_artifact() } } -std::string new_natural_artifact( artifact_natural_property prop ) +itype_id new_natural_artifact( artifact_natural_property prop ) { // Natural artifacts are always tools. it_artifact_tool def; @@ -1041,7 +1041,7 @@ std::string new_natural_artifact( artifact_natural_property prop ) } // Make a special debugging artifact. -std::string architects_cube() +itype_id architects_cube() { it_artifact_tool def; @@ -1136,7 +1136,7 @@ void load_artifacts( const std::string &path ) void it_artifact_tool::deserialize( const JsonObject &jo ) { - id = jo.get_string( "id" ); + jo.read( "id", id, true ); name = no_translation( jo.get_string( "name" ) ); description = no_translation( jo.get_string( "description" ) ); if( jo.has_int( "sym" ) ) { @@ -1188,7 +1188,7 @@ void it_artifact_tool::deserialize( const JsonObject &jo ) } tool->revert_to.emplace( jo.get_string( "revert_to", "null" ) ); - if( *tool->revert_to == "null" ) { + if( tool->revert_to->is_null() ) { tool->revert_to.reset(); } @@ -1244,7 +1244,7 @@ void it_artifact_tool::deserialize( const JsonObject &jo ) void it_artifact_armor::deserialize( const JsonObject &jo ) { - id = jo.get_string( "id" ); + jo.read( "id", id, true ); name = no_translation( jo.get_string( "name" ) ); description = no_translation( jo.get_string( "description" ) ); if( jo.has_int( "sym" ) ) { diff --git a/src/artifact.h b/src/artifact.h index 9a5e4818cff05..40829bac967f3 100644 --- a/src/artifact.h +++ b/src/artifact.h @@ -121,9 +121,9 @@ class it_artifact_armor : public itype /* FUNCTIONS */ -std::string new_artifact(); -std::string new_natural_artifact( artifact_natural_property prop ); -std::string architects_cube(); +itype_id new_artifact(); +itype_id new_natural_artifact( artifact_natural_property prop ); +itype_id architects_cube(); // note: needs to be called by main() before MAPBUFFER.load void load_artifacts( const std::string &path ); diff --git a/src/avatar.cpp b/src/avatar.cpp index ca3832f1e006a..2de1ceadfc911 100644 --- a/src/avatar.cpp +++ b/src/avatar.cpp @@ -88,6 +88,8 @@ static const efftype_id effect_slept_through_alarm( "slept_through_alarm" ); static const efftype_id effect_stim( "stim" ); static const efftype_id effect_stim_overdose( "stim_overdose" ); +static const itype_id itype_guidebook( "guidebook" ); + static const trait_id trait_ARACHNID_ARMS( "ARACHNID_ARMS" ); static const trait_id trait_ARACHNID_ARMS_OK( "ARACHNID_ARMS_OK" ); static const trait_id trait_CENOBITE( "CENOBITE" ); @@ -418,7 +420,7 @@ bool avatar::read( item &it, const bool continuous ) return true; } - if( it.typeId() == "guidebook" ) { + if( it.typeId() == itype_guidebook ) { // special guidebook effect: print a misc. hint when read if( reader != this ) { add_msg( m_info, fail_messages[0] ); @@ -922,7 +924,7 @@ void avatar::do_read( item &book ) activity.set_to_null(); } -bool avatar::has_identified( const std::string &item_id ) const +bool avatar::has_identified( const itype_id &item_id ) const { return items_identified.count( item_id ) > 0; } diff --git a/src/avatar.h b/src/avatar.h index 2b21b143a7d49..d6a4cb5b9b46b 100644 --- a/src/avatar.h +++ b/src/avatar.h @@ -160,7 +160,7 @@ class avatar : public player /** Completes book reading action. **/ void do_read( item &book ); /** Note that we've read a book at least once. **/ - bool has_identified( const std::string &item_id ) const override; + bool has_identified( const itype_id &item_id ) const override; hint_rating rate_action_read( const item &it ) const; @@ -251,7 +251,7 @@ class avatar : public player mission *active_mission; // Items the player has identified. - std::unordered_set items_identified; + std::unordered_set items_identified; object_type grab_type; diff --git a/src/avatar_action.cpp b/src/avatar_action.cpp index cd2497ff50be7..6275eee00e247 100644 --- a/src/avatar_action.cpp +++ b/src/avatar_action.cpp @@ -68,6 +68,13 @@ static const efftype_id effect_relax_gas( "relax_gas" ); static const efftype_id effect_ridden( "ridden" ); static const efftype_id effect_stunned( "stunned" ); +static const itype_id itype_adv_UPS_off( "adv_UPS_off" ); +static const itype_id itype_grass( "grass" ); +static const itype_id itype_swim_fins( "swim_fins" ); +static const itype_id itype_underbrush( "underbrush" ); +static const itype_id itype_UPS( "UPS" ); +static const itype_id itype_UPS_off( "UPS_off" ); + static const skill_id skill_swimming( "swimming" ); static const bionic_id bio_ups( "bio_ups" ); @@ -532,8 +539,9 @@ void avatar_action::swim( map &m, avatar &you, const tripoint &p ) int movecost = you.swim_speed(); you.practice( skill_swimming, you.is_underwater() ? 2 : 1 ); if( movecost >= 500 ) { - if( !you.is_underwater() && !( you.shoe_type_count( "swim_fins" ) == 2 || - ( you.shoe_type_count( "swim_fins" ) == 1 && one_in( 2 ) ) ) ) { + if( !you.is_underwater() && + !( you.shoe_type_count( itype_swim_fins ) == 2 || + ( you.shoe_type_count( itype_swim_fins ) == 1 && one_in( 2 ) ) ) ) { add_msg( m_bad, _( "You sink like a rock!" ) ); you.set_underwater( true ); ///\EFFECT_STR increases breath-holding capacity while sinking @@ -691,13 +699,13 @@ static bool gunmode_checks_weapon( avatar &you, const map &m, std::vectoru.mounted_creature.get(); - if( !mons->type->mech_weapon.empty() ) { + if( !mons->type->mech_weapon.is_empty() ) { is_mech_weapon = true; } } if( !is_mech_weapon ) { - if( !( you.has_charges( "UPS_off", ups_drain ) || - you.has_charges( "adv_UPS_off", adv_ups_drain ) || + if( !( you.has_charges( itype_UPS_off, ups_drain ) || + you.has_charges( itype_adv_UPS_off, adv_ups_drain ) || ( you.has_active_bionic( bio_ups ) && you.get_power_level() >= units::from_kilojoule( ups_drain ) ) ) ) { messages.push_back( string_format( @@ -706,7 +714,7 @@ static bool gunmode_checks_weapon( avatar &you, const map &m, std::vectortname() ) ); result = false; @@ -955,7 +963,7 @@ void avatar_action::fire_wielded_weapon( avatar &you, map &m ) return; } else if( weapon.ammo_data() && !weapon.ammo_types().count( weapon.ammo_data()->ammo->type ) ) { add_msg( m_info, _( "The %s can't be fired while loaded with incompatible ammunition %s" ), - weapon.tname(), weapon.ammo_current() ); + weapon.tname(), weapon.ammo_current()->nname( 1 ) ); return; } diff --git a/src/basecamp.cpp b/src/basecamp.cpp index 8573b5ca59657..fd3782e9c8dab 100644 --- a/src/basecamp.cpp +++ b/src/basecamp.cpp @@ -303,7 +303,7 @@ std::vector basecamp::available_upgrades( const point &dir ) expansion_data &e_data = e->second; for( const recipe *recp_p : recipe_dict.all_blueprints() ) { const recipe &recp = *recp_p; - const std::string &bldg = recp.result(); + const std::string &bldg = recp.result().str(); // skip buildings that are completed if( e_data.provides.find( bldg ) != e_data.provides.end() ) { continue; @@ -647,7 +647,7 @@ void basecamp::form_crafting_inventory( map &target_map ) bcp_r.consumed = 0; item camp_item( bcp_r.fake_id, 0 ); camp_item.item_tags.insert( "PSEUDO" ); - if( bcp_r.ammo_id != "NULL" ) { + if( !bcp_r.ammo_id.is_null() ) { for( basecamp_fuel &bcp_f : fuels ) { if( bcp_f.ammo_id == bcp_r.ammo_id ) { if( bcp_f.available > 0 ) { diff --git a/src/basecamp.h b/src/basecamp.h index 06b28f86930c9..f3778a672f3eb 100644 --- a/src/basecamp.h +++ b/src/basecamp.h @@ -44,7 +44,6 @@ struct expansion_data { using npc_ptr = shared_ptr_fast; using comp_list = std::vector; using Group_tag = std::string; -using itype_id = std::string; namespace catacurses { diff --git a/src/bionics.cpp b/src/bionics.cpp index 920078b499a94..f566a7ac705e7 100644 --- a/src/bionics.cpp +++ b/src/bionics.cpp @@ -120,9 +120,20 @@ static const efftype_id effect_visuals( "visuals" ); static const efftype_id effect_weed_high( "weed_high" ); static const itype_id fuel_type_battery( "battery" ); +static const itype_id fuel_type_metabolism( "metabolism" ); +static const itype_id fuel_type_muscle( "muscle" ); static const itype_id fuel_type_sun_light( "sunlight" ); static const itype_id fuel_type_wind( "wind" ); +static const itype_id itype_adv_UPS_off( "adv_UPS_off" ); +static const itype_id itype_anesthetic( "anesthetic" ); +static const itype_id itype_pseudo_bio_picklock( "psuedo_bio_picklock" ); +static const itype_id itype_radiocontrol( "radiocontrol" ); +static const itype_id itype_remotevehcontrol( "remotevehcontrol" ); +static const itype_id itype_UPS( "UPS" ); +static const itype_id itype_UPS_off( "UPS_off" ); +static const itype_id itype_water_clean( "water_clean" ); + static const fault_id fault_bionic_salvaged( "fault_bionic_salvaged" ); static const skill_id skill_computer( "computer" ); @@ -233,6 +244,13 @@ bool bionic_data::has_flag( const std::string &flag ) const return flags.count( flag ) > 0; } +itype_id bionic_data::itype() const +{ + // For now we just assume that the bionic id matches the corresponding item + // id (as strings). + return itype_id( id.str() ); +} + bool bionic_data::is_included( const bionic_id &id ) const { return std::find( included_bionics.begin(), included_bionics.end(), id ) != included_bionics.end(); @@ -259,7 +277,7 @@ void bionic_data::load( const JsonObject &jsobj, const std::string ) optional( jsobj, was_loaded, "fuel_efficiency", fuel_efficiency, 0 ); optional( jsobj, was_loaded, "passive_fuel_efficiency", passive_fuel_efficiency, 0 ); - optional( jsobj, was_loaded, "fake_item", fake_item, "" ); + optional( jsobj, was_loaded, "fake_item", fake_item, itype_id() ); optional( jsobj, was_loaded, "enchantments", enchantments ); @@ -367,7 +385,7 @@ void bionic_data::check_bionic_consistency() if( bio.has_flag( flag_BIO_GUN ) && bio.has_flag( flag_BIO_WEAPON ) ) { debugmsg( "Bionic %s specified as both gun and weapon bionic", bio.id.c_str() ); } - if( !bio.fake_item.empty() && + if( !bio.fake_item.is_empty() && !item::type_is_defined( bio.fake_item ) ) { debugmsg( "Bionic %s has unknown fake_item %s", bio.id.c_str(), bio.fake_item.c_str() ); @@ -401,7 +419,7 @@ void bionic_data::check_bionic_consistency() bio.id.c_str(), bio.upgraded_bionic.c_str() ); } } - if( !item::type_is_defined( bio.id.c_str() ) && !bio.included ) { + if( !item::type_is_defined( bio.itype() ) && !bio.included ) { debugmsg( "Bionic %s has no defined item version", bio.id.c_str() ); } } @@ -466,7 +484,7 @@ void npc::check_or_use_weapon_cbm( const bionic_id &cbm_id ) return; } - const int ups_charges = charges_of( "UPS" ); + const int ups_charges = charges_of( itype_UPS ); int ammo_count = weapon.ammo_remaining(); const int ups_drain = weapon.get_gun_ups_drain(); if( ups_drain > 0 ) { @@ -511,9 +529,9 @@ bool Character::activate_bionic( int b, bool eff_only ) } // Special compatibility code for people who updated saves with their claws out - if( ( weapon.typeId() == static_cast( bio_claws_weapon ) && + if( ( weapon.typeId().str() == bio_claws_weapon.str() && bio.id == bio_claws_weapon ) || - ( weapon.typeId() == static_cast( bio_blade_weapon ) && + ( weapon.typeId().str() == bio_blade_weapon.str() && bio.id == bio_blade_weapon ) ) { return deactivate_bionic( b ); } @@ -863,7 +881,7 @@ bool Character::activate_bionic( int b, bool eff_only ) no_target = false; if( query_yn( _( "Extract water from the %s" ), colorize( it.tname(), it.color_in_inventory() ) ) ) { - item water( "water_clean", calendar::turn, avail ); + item water( itype_water_clean, calendar::turn, avail ); water.set_item_temperature( 0.00001 * it.temperature ); if( liquid_handler::consume_liquid( water ) ) { add_msg_activate(); @@ -925,9 +943,9 @@ bool Character::activate_bionic( int b, bool eff_only ) g->refresh_all(); const cata::optional pnt = choose_adjacent( _( "Use your lockpick where?" ) ); if( pnt && g->m.has_flag( "PICKABLE", *pnt ) ) { - g->u.i_add( item( "pseudo_bio_picklock" ) ); + g->u.i_add( item( itype_pseudo_bio_picklock ) ); std::vector bio_picklocks = g->u.items_with( []( const item & itm ) { - return itm.typeId() == "pseudo_bio_picklock"; + return itm.typeId() == itype_pseudo_bio_picklock; } ); if( !bio_picklocks.empty() ) { add_msg_activate(); @@ -1076,7 +1094,7 @@ bool Character::activate_bionic( int b, bool eff_only ) reset(); // Also reset crafting inventory cache if this bionic spawned a fake item - if( !bio.info().fake_item.empty() ) { + if( !bio.info().fake_item.is_empty() ) { invalidate_crafting_inventory(); } @@ -1130,7 +1148,8 @@ bool Character::deactivate_bionic( int b, bool eff_only ) add_msg_if_npc( m_info, _( " withdraws %s %s." ), disp_name( true ), weapon.tname() ); } - bio.ammo_loaded = weapon.ammo_data() != nullptr ? weapon.ammo_data()->get_id() : "null"; + bio.ammo_loaded = + weapon.ammo_data() != nullptr ? weapon.ammo_data()->get_id() : itype_id::NULL_ID(); bio.ammo_count = static_cast( weapon.ammo_remaining() ); weapon = item(); invalidate_crafting_inventory(); @@ -1138,9 +1157,10 @@ bool Character::deactivate_bionic( int b, bool eff_only ) } else if( bio.id == bio_cqb ) { martial_arts_data.selected_style_check(); } else if( bio.id == bio_remote ) { - if( g->remoteveh() != nullptr && !has_active_item( "remotevehcontrol" ) ) { + if( g->remoteveh() != nullptr && !has_active_item( itype_remotevehcontrol ) ) { g->setremoteveh( nullptr ); - } else if( !get_value( "remote_controlling" ).empty() && !has_active_item( "radiocontrol" ) ) { + } else if( !get_value( "remote_controlling" ).empty() && + !has_active_item( itype_radiocontrol ) ) { set_value( "remote_controlling", "" ); } } else if( bio.id == bio_tools ) { @@ -1155,7 +1175,7 @@ bool Character::deactivate_bionic( int b, bool eff_only ) } // Also reset crafting inventory cache if this bionic spawned a fake item - if( !bio.info().fake_item.empty() ) { + if( !bio.info().fake_item.is_empty() ) { invalidate_crafting_inventory(); } @@ -1172,17 +1192,17 @@ bool Character::burn_fuel( int b, bool start ) { bionic &bio = ( *my_bionics )[b]; if( ( bio.info().fuel_opts.empty() && !bio.info().is_remote_fueled ) || - bio.is_this_fuel_powered( "muscle" ) ) { + bio.is_this_fuel_powered( fuel_type_muscle ) ) { return true; } - const bool is_metabolism_powered = bio.is_this_fuel_powered( "metabolism" ); + const bool is_metabolism_powered = bio.is_this_fuel_powered( fuel_type_metabolism ); const bool is_cable_powered = bio.info().is_remote_fueled; std::vector fuel_available = get_fuel_available( bio.id ); float effective_efficiency = get_effective_efficiency( b, bio.info().fuel_efficiency ); if( is_cable_powered ) { const itype_id remote_fuel = find_remote_fuel(); - if( !remote_fuel.empty() ) { + if( !remote_fuel.is_empty() ) { fuel_available.emplace_back( remote_fuel ); if( remote_fuel == fuel_type_sun_light ) { effective_efficiency = item_worn_with_flag( "SOLARPACK_ON" ).type->solar_efficiency; @@ -1221,9 +1241,9 @@ bool Character::burn_fuel( int b, bool start ) } else if( is_perpetual_fuel ) { current_fuel_stock = 1; } else if( is_cable_powered ) { - current_fuel_stock = std::stoi( get_value( "rem_" + fuel ) ); + current_fuel_stock = std::stoi( get_value( "rem_" + fuel.str() ) ); } else { - current_fuel_stock = std::stoi( get_value( fuel ) ); + current_fuel_stock = std::stoi( get_value( fuel.str() ) ); } if( !bio.has_flag( flag_SAFE_FUEL_OFF ) && @@ -1284,10 +1304,10 @@ bool Character::burn_fuel( int b, bool start ) } else if( to_consume == 1 ) { current_fuel_stock = 0; } - set_value( "rem_" + fuel, std::to_string( current_fuel_stock ) ); + set_value( "rem_" + fuel.str(), std::to_string( current_fuel_stock ) ); } else { current_fuel_stock -= 1; - set_value( fuel, std::to_string( current_fuel_stock ) ); + set_value( fuel.str(), std::to_string( current_fuel_stock ) ); update_fuel_storage( fuel ); mod_power_level( units::from_kilojoule( fuel_energy ) * effective_efficiency ); } @@ -1302,7 +1322,7 @@ bool Character::burn_fuel( int b, bool start ) _( "Stored calories are below the safe threshold, 's %s shuts down to preserve their health." ), bio.info().name ); } else { - remove_value( fuel ); + remove_value( fuel.str() ); add_msg_player_or_npc( m_info, _( "Your %s runs out of fuel and turn off." ), _( "'s %s runs out of fuel and turn off." ), @@ -1323,7 +1343,7 @@ void Character::passive_power_gen( int b ) { const bionic &bio = ( *my_bionics )[b]; const float passive_fuel_efficiency = bio.info().passive_fuel_efficiency; - if( bio.info().fuel_opts.empty() || bio.is_this_fuel_powered( "muscle" ) || + if( bio.info().fuel_opts.empty() || bio.is_this_fuel_powered( fuel_type_muscle ) || passive_fuel_efficiency == 0.0 ) { return; } @@ -1386,11 +1406,11 @@ itype_id Character::find_remote_fuel( bool look_only ) return itm.get_var( "cable" ) == "plugged_in"; }; if( !look_only ) { - if( has_charges( "UPS_off", 1, used_ups ) ) { - set_value( "rem_battery", std::to_string( charges_of( "UPS_off", + if( has_charges( itype_UPS_off, 1, used_ups ) ) { + set_value( "rem_battery", std::to_string( charges_of( itype_UPS_off, units::to_kilojoule( max_power_level ), used_ups ) ) ); - } else if( has_charges( "adv_UPS_off", 1, used_ups ) ) { - set_value( "rem_battery", std::to_string( charges_of( "adv_UPS_off", + } else if( has_charges( itype_adv_UPS_off, 1, used_ups ) ) { + set_value( "rem_battery", std::to_string( charges_of( itype_adv_UPS_off, units::to_kilojoule( max_power_level ), used_ups ) ) ); } else { set_value( "rem_battery", std::to_string( 0 ) ); @@ -1436,11 +1456,11 @@ int Character::consume_remote_fuel( int amount ) static const item_filter used_ups = [&]( const item & itm ) { return itm.get_var( "cable" ) == "plugged_in"; }; - if( has_charges( "UPS_off", unconsumed_amount, used_ups ) ) { - use_charges( "UPS_off", unconsumed_amount, used_ups ); + if( has_charges( itype_UPS_off, unconsumed_amount, used_ups ) ) { + use_charges( itype_UPS_off, unconsumed_amount, used_ups ); unconsumed_amount -= 1; - } else if( has_charges( "adv_UPS_off", unconsumed_amount, used_ups ) ) { - use_charges( "adv_UPS_off", roll_remainder( unconsumed_amount * 0.6 ), used_ups ); + } else if( has_charges( itype_adv_UPS_off, unconsumed_amount, used_ups ) ) { + use_charges( itype_adv_UPS_off, roll_remainder( unconsumed_amount * 0.6 ), used_ups ); unconsumed_amount -= 1; } } @@ -1547,12 +1567,13 @@ void Character::process_bionic( int b ) std::vector fuel_available = get_fuel_available( bio.id ); if( bio.id->is_remote_fueled ) { const itype_id rem_fuel = find_remote_fuel(); - const std::string rem_amount = get_value( "rem_" + rem_fuel ); + const std::string rem_amount = get_value( "rem_" + rem_fuel.str() ); int rem_fuel_stock = 0; if( !rem_amount.empty() ) { rem_fuel_stock = std::stoi( rem_amount ); } - if( !rem_fuel.empty() && ( rem_fuel_stock > 0 || item( rem_fuel ).has_flag( flag_PERPETUAL ) ) ) { + if( !rem_fuel.is_empty() && ( rem_fuel_stock > 0 || + item( rem_fuel ).has_flag( flag_PERPETUAL ) ) ) { fuel_available.emplace_back( rem_fuel ); } } @@ -1872,7 +1893,7 @@ void Character::bionics_uninstall_failure( monster &installer, player &patient, bool Character::has_enough_anesth( const itype &cbm, player &patient ) { if( !cbm.bionic ) { - debugmsg( "has_enough_anesth( const itype *cbm ): %s is not a bionic", cbm.get_id() ); + debugmsg( "has_enough_anesth( const itype *cbm ): %s is not a bionic", cbm.get_id().str() ); return false; } @@ -2052,8 +2073,8 @@ bool Character::can_uninstall_bionic( const bionic_id &b_id, player &installer, { // if malfunctioning bionics doesn't have associated item it gets a difficulty of 12 int difficulty = 12; - if( item::type_is_defined( b_id.c_str() ) ) { - auto type = item::find_type( b_id.c_str() ); + if( item::type_is_defined( b_id->itype() ) ) { + auto type = item::find_type( b_id->itype() ); if( type->bionic ) { difficulty = type->bionic->difficulty; } @@ -2117,8 +2138,8 @@ bool Character::uninstall_bionic( const bionic_id &b_id, player &installer, bool { // if malfunctioning bionics doesn't have associated item it gets a difficulty of 12 int difficulty = 12; - if( item::type_is_defined( b_id.c_str() ) ) { - auto type = item::find_type( b_id.c_str() ); + if( item::type_is_defined( b_id->itype() ) ) { + auto type = item::find_type( b_id->itype() ); if( type->bionic ) { difficulty = type->bionic->difficulty; } @@ -2178,7 +2199,7 @@ void Character::perform_uninstall( bionic_id bid, int difficulty, int success, mod_max_power_level( -power_lvl ); item cbm( "burnt_out_bionic" ); - if( item::type_is_defined( bid.c_str() ) ) { + if( item::type_is_defined( bid->itype() ) ) { cbm = item( bid.c_str() ); } cbm.set_flag( flag_FILTHY ); @@ -2202,9 +2223,7 @@ void Character::perform_uninstall( bionic_id bid, int difficulty, int success, bool Character::uninstall_bionic( const bionic &target_cbm, monster &installer, player &patient, float adjusted_skill ) { - const std::string ammo_type( "anesthetic" ); - - if( installer.ammo[ammo_type] <= 0 ) { + if( installer.ammo[itype_anesthetic] <= 0 ) { if( g->u.sees( installer ) ) { add_msg( _( "The %s's anesthesia kit looks empty." ), installer.name() ); } @@ -2232,7 +2251,7 @@ bool Character::uninstall_bionic( const bionic &target_cbm, monster &installer, installer.name(), patient.disp_name() ); } - installer.ammo[ammo_type] -= 1; + installer.ammo[itype_anesthetic] -= 1; patient.add_effect( effect_narcosis, duration ); patient.add_effect( effect_sleep, duration ); @@ -2259,7 +2278,7 @@ bool Character::uninstall_bionic( const bionic &target_cbm, monster &installer, patient.mod_max_power_level( -target_cbm.info().capacity ); patient.remove_bionic( target_cbm.id ); item cbm( "burnt_out_bionic" ); - if( item::type_is_defined( target_cbm.id.c_str() ) ) { + if( item::type_is_defined( target_cbm.info().itype() ) ) { cbm = item( target_cbm.id.c_str() ); } cbm.set_flag( flag_FILTHY ); @@ -2761,7 +2780,7 @@ bool bionic::has_flag( const std::string &flag ) const int bionic::get_quality( const quality_id &quality ) const { const auto &i = info(); - if( i.fake_item.empty() ) { + if( i.fake_item.is_empty() ) { return INT_MIN; } @@ -2864,7 +2883,7 @@ void bionic::deserialize( JsonIn &jsin ) powered = jo.get_bool( "powered" ); charge_timer = jo.get_int( "charge" ); if( jo.has_string( "ammo_loaded" ) ) { - ammo_loaded = jo.get_string( "ammo_loaded" ); + jo.read( "ammo_loaded", ammo_loaded, true ); } if( jo.has_int( "ammo_count" ) ) { ammo_count = jo.get_int( "ammo_count" ); diff --git a/src/bionics.h b/src/bionics.h index 3a09b1dd1c736..eafbce73c2529 100644 --- a/src/bionics.h +++ b/src/bionics.h @@ -23,8 +23,6 @@ class JsonObject; class JsonOut; class player; -using itype_id = std::string; - struct bionic_data { bionic_data(); @@ -97,7 +95,7 @@ struct bionic_data { * Fake item created for crafting with this bionic available. * Also the item used for gun bionics. */ - std::string fake_item; + itype_id fake_item; /** * Mutations/trait that are removed upon installing this CBM. * E.g. enhanced optic bionic may cancel HYPEROPIC trait. @@ -132,6 +130,8 @@ struct bionic_data { cata::flat_set flags; bool has_flag( const std::string &flag ) const; + itype_id itype() const; + bool is_included( const bionic_id &id ) const; bool was_loaded = false; @@ -147,7 +147,7 @@ struct bionic { char invlet = 'a'; bool powered = false; /* Ammunition actually loaded in this bionic gun in deactivated state */ - itype_id ammo_loaded = "null"; + itype_id ammo_loaded = itype_id::NULL_ID(); /* Ammount of ammo actually held inside by this bionic gun in deactivated state */ unsigned int ammo_count = 0; /* An amount of time during which this bionic has been rendered inoperative. */ diff --git a/src/bionics_ui.cpp b/src/bionics_ui.cpp index 89d204f54370d..f8a7ef9202e81 100644 --- a/src/bionics_ui.cpp +++ b/src/bionics_ui.cpp @@ -84,17 +84,17 @@ static void draw_bionics_titlebar( const catacurses::window &window, player *p, fuel_string += colorize( temp_fuel.tname(), c_green ) + " "; continue; } - fuel_string += temp_fuel.tname() + ": " + colorize( p->get_value( fuel ), + fuel_string += temp_fuel.tname() + ": " + colorize( p->get_value( fuel.str() ), c_green ) + "/" + std::to_string( p->get_total_fuel_capacity( fuel ) ) + " "; } if( bio.info().is_remote_fueled && p->has_active_bionic( bio.id ) ) { const itype_id rem_fuel = p->find_remote_fuel( true ); - if( !rem_fuel.empty() ) { + if( !rem_fuel.is_empty() ) { const item tmp_rem_fuel( rem_fuel ); if( tmp_rem_fuel.has_flag( flag_PERPETUAL ) ) { fuel_string += colorize( tmp_rem_fuel.tname(), c_green ) + " "; } else { - fuel_string += tmp_rem_fuel.tname() + ": " + colorize( p->get_value( "rem_" + rem_fuel ), + fuel_string += tmp_rem_fuel.tname() + ": " + colorize( p->get_value( "rem_" + rem_fuel.str() ), c_green ) + " "; } found_fuel = true; diff --git a/src/cata_tiles.cpp b/src/cata_tiles.cpp index 2693634bcc025..8e4216b9dcdf3 100644 --- a/src/cata_tiles.cpp +++ b/src/cata_tiles.cpp @@ -72,6 +72,8 @@ static const efftype_id effect_ridden( "ridden" ); +static const itype_id itype_corpse( "corpse" ); + static const std::string ITEM_HIGHLIGHT( "highlight_item" ); static const std::string ZOMBIE_REVIVAL_INDICATOR( "zombie_revival_indicator" ); @@ -1539,15 +1541,15 @@ const tile_type *cata_tiles::find_tile_looks_like( std::string &id, TILE_CATEGOR const vpart_info &new_vpi = new_vpid.obj(); looks_like = "vp_" + new_vpi.looks_like; } else if( category == C_ITEM ) { - if( !item::type_is_defined( looks_like ) ) { + if( !item::type_is_defined( itype_id( looks_like ) ) ) { if( looks_like.substr( 0, 7 ) == "corpse_" ) { looks_like = "corpse"; continue; } return nullptr; } - const itype *new_it = item::find_type( looks_like ); - looks_like = new_it->looks_like; + const itype *new_it = item::find_type( itype_id( looks_like ) ); + looks_like = new_it->looks_like.str(); } else { return nullptr; } @@ -1588,11 +1590,11 @@ bool cata_tiles::find_overlay_looks_like( const bool male, const std::string &ov looks_like = "mutation_" + looks_like.substr( 16 ); continue; } - if( !item::type_is_defined( looks_like ) ) { + if( !item::type_is_defined( itype_id( looks_like ) ) ) { break; } - const itype *new_it = item::find_type( looks_like ); - looks_like = new_it->looks_like; + const itype *new_it = item::find_type( itype_id( looks_like ) ); + looks_like = new_it->looks_like.str(); } return exists; } @@ -1676,7 +1678,7 @@ bool cata_tiles::draw_from_id_string( std::string id, TILE_CATEGORY category, } else if( category == C_ITEM ) { item tmp; if( 0 == id.compare( 0, 7, "corpse_" ) ) { - tmp = item( "corpse", 0 ); + tmp = item( itype_corpse, 0 ); } else { tmp = item( id, 0 ); } @@ -2566,9 +2568,9 @@ bool cata_tiles::draw_field_or_item( const tripoint &p, const lit_level ll, int } else { it_type = nullptr; } - if( it_type && it_id != "null" ) { - const std::string disp_id = it_id == "corpse" && mon_id ? - "corpse_" + mon_id.str() : it_id; + if( it_type && !it_id.is_null() ) { + const std::string disp_id = it_id == itype_corpse && mon_id ? + "corpse_" + mon_id.str() : it_id.str(); const std::string it_category = it_type->get_item_type_string(); const lit_level lit = it_overridden ? LL_LIT : ll; const bool nv = it_overridden ? false : nv_goggles_activated; diff --git a/src/cata_tiles.h b/src/cata_tiles.h index d4c35be85583b..99cd04c8486fe 100644 --- a/src/cata_tiles.h +++ b/src/cata_tiles.h @@ -29,8 +29,6 @@ class Character; class JsonObject; class pixel_minimap; -using itype_id = std::string; - extern void set_displaybuffer_rendertarget(); /** Structures */ diff --git a/src/cata_variant.h b/src/cata_variant.h index c46d5da77848b..1f0eaa65728c2 100644 --- a/src/cata_variant.h +++ b/src/cata_variant.h @@ -25,8 +25,6 @@ enum class mutagen_technique : int; enum hp_part : int; enum character_movemode : int; -using itype_id = std::string; - // cata_variant is a variant-like type that stores a variety of different cata // types. All types are stored by converting them to a string. @@ -217,7 +215,7 @@ struct convert { }; template<> -struct convert : convert_string {}; +struct convert : convert_string_id {}; template<> struct convert : convert_string_id {}; diff --git a/src/character.cpp b/src/character.cpp index 6837c8b9138c3..c77b220c56ba1 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -174,6 +174,20 @@ static const efftype_id effect_took_xanax( "took_xanax" ); static const efftype_id effect_webbed( "webbed" ); static const efftype_id effect_winded( "winded" ); +static const itype_id itype_adv_UPS_off( "adv_UPS_off" ); +static const itype_id itype_apparatus( "apparatus" ); +static const itype_id itype_beartrap( "breatrap" ); +static const itype_id itype_e_handcuffs( "e_handcuffs" ); +static const itype_id itype_fire( "fire" ); +static const itype_id itype_pseudo_bio_picklock( "pseudo_bio_picklock" ); +static const itype_id itype_rm13_armor_on( "rm13_armor_on" ); +static const itype_id itype_rope_6( "rope_6" ); +static const itype_id itype_snare_trigger( "snare_trigger" ); +static const itype_id itype_string_36( "string_36" ); +static const itype_id itype_toolset( "toolset" ); +static const itype_id itype_UPS( "UPS" ); +static const itype_id itype_UPS_off( "UPS_off" ); + static const skill_id skill_archery( "archery" ); static const skill_id skill_dodge( "dodge" ); static const skill_id skill_pistol( "pistol" ); @@ -1072,7 +1086,7 @@ void Character::mount_creature( monster &z ) z.facing = facing; add_msg_if_player( m_good, _( "You climb on the %s." ), z.get_name() ); if( z.has_flag( MF_RIDEABLE_MECH ) ) { - if( !z.type->mech_weapon.empty() ) { + if( !z.type->mech_weapon.is_empty() ) { item mechwep = item( z.type->mech_weapon ); wield( mechwep ); } @@ -1153,7 +1167,7 @@ void Character::forced_dismount() bool mech = false; if( mounted_creature ) { auto mon = mounted_creature.get(); - if( mon->has_flag( MF_RIDEABLE_MECH ) && !mon->type->mech_weapon.empty() ) { + if( mon->has_flag( MF_RIDEABLE_MECH ) && !mon->type->mech_weapon.is_empty() ) { mech = true; remove_item( weapon ); } @@ -1260,7 +1274,7 @@ void Character::dismount() remove_effect( effect_riding ); monster *critter = mounted_creature.get(); critter->mounted_player_id = character_id(); - if( critter->has_flag( MF_RIDEABLE_MECH ) && !critter->type->mech_weapon.empty() ) { + if( critter->has_flag( MF_RIDEABLE_MECH ) && !critter->type->mech_weapon.is_empty() ) { remove_item( weapon ); } if( is_avatar() && g->u.get_grab_type() != OBJECT_NONE ) { @@ -1376,8 +1390,8 @@ bool Character::move_effects( bool attacking ) if( x_in_y( mon->type->melee_dice * mon->type->melee_sides, 12 ) ) { mon->remove_effect( effect_lightsnare ); remove_effect( effect_lightsnare ); - g->m.spawn_item( pos(), "string_36" ); - g->m.spawn_item( pos(), "snare_trigger" ); + g->m.spawn_item( pos(), itype_string_36 ); + g->m.spawn_item( pos(), itype_snare_trigger ); add_msg( _( "The %s escapes the light snare!" ), mon->get_name() ); } } else { @@ -1406,8 +1420,8 @@ bool Character::move_effects( bool attacking ) if( x_in_y( mon->type->melee_dice * mon->type->melee_sides, 32 ) ) { mon->remove_effect( effect_heavysnare ); remove_effect( effect_heavysnare ); - g->m.spawn_item( pos(), "rope_6" ); - g->m.spawn_item( pos(), "snare_trigger" ); + g->m.spawn_item( pos(), itype_rope_6 ); + g->m.spawn_item( pos(), itype_snare_trigger ); add_msg( _( "The %s escapes the heavy snare!" ), mon->get_name() ); } } @@ -1444,7 +1458,7 @@ bool Character::move_effects( bool attacking ) if( x_in_y( mon->type->melee_dice * mon->type->melee_sides, 200 ) ) { mon->remove_effect( effect_beartrap ); remove_effect( effect_beartrap ); - g->m.spawn_item( pos(), "beartrap" ); + g->m.spawn_item( pos(), itype_beartrap ); add_msg( _( "The %s escapes the bear trap!" ), mon->get_name() ); } else { add_msg_if_player( m_bad, @@ -1689,7 +1703,7 @@ void Character::recalc_sight_limits() if( has_nv() ) { vision_mode_cache.set( NV_GOGGLES ); } - if( has_active_mutation( trait_NIGHTVISION3 ) || is_wearing( "rm13_armor_on" ) || + if( has_active_mutation( trait_NIGHTVISION3 ) || is_wearing( itype_rm13_armor_on ) || ( is_mounted() && mounted_creature->has_flag( MF_MECH_RECON_VISION ) ) ) { vision_mode_cache.set( NIGHTVISION_3 ); } @@ -1978,7 +1992,7 @@ std::vector Character::get_fuel_available( const bionic_id &bio ) cons std::vector stored_fuels; for( const itype_id &fuel : bio->fuel_opts ) { const item tmp_fuel( fuel ); - if( !get_value( fuel ).empty() || tmp_fuel.has_flag( flag_PERPETUAL ) ) { + if( !get_value( fuel.str() ).empty() || tmp_fuel.has_flag( flag_PERPETUAL ) ) { stored_fuels.emplace_back( fuel ); } } @@ -1988,13 +2002,13 @@ std::vector Character::get_fuel_available( const bionic_id &bio ) cons int Character::get_fuel_capacity( const itype_id &fuel ) const { int amount_stored = 0; - if( !get_value( fuel ).empty() ) { - amount_stored = std::stoi( get_value( fuel ) ); + if( !get_value( fuel.str() ).empty() ) { + amount_stored = std::stoi( get_value( fuel.str() ) ); } int capacity = 0; for( const bionic_id &bid : get_bionics() ) { for( const itype_id &fl : bid->fuel_opts ) { - if( get_value( bid.c_str() ).empty() || get_value( bid.c_str() ) == fl ) { + if( get_value( bid.str() ).empty() || get_value( bid.str() ) == fl.str() ) { if( fl == fuel ) { capacity += bid->fuel_capacity; } @@ -2009,7 +2023,7 @@ int Character::get_total_fuel_capacity( const itype_id &fuel ) const int capacity = 0; for( const bionic_id &bid : get_bionics() ) { for( const itype_id &fl : bid->fuel_opts ) { - if( get_value( bid.c_str() ).empty() || get_value( bid.c_str() ) == fl ) { + if( get_value( bid.str() ).empty() || get_value( bid.str() ) == fl.str() ) { if( fl == fuel ) { capacity += bid->fuel_capacity; } @@ -2022,7 +2036,7 @@ int Character::get_total_fuel_capacity( const itype_id &fuel ) const void Character::update_fuel_storage( const itype_id &fuel ) { const item it( fuel ); - if( get_value( fuel ).empty() ) { + if( get_value( fuel.str() ).empty() ) { for( const bionic_id &bid : get_bionic_fueled_with( it ) ) { remove_value( bid.c_str() ); } @@ -2033,7 +2047,7 @@ void Character::update_fuel_storage( const itype_id &fuel ) if( bids.empty() ) { return; } - int amount_fuel_loaded = std::stoi( get_value( fuel ) ); + int amount_fuel_loaded = std::stoi( get_value( fuel.str() ) ); std::vector loaded_bio; // Sort bionic in order of decreasing capacity @@ -2061,7 +2075,7 @@ void Character::update_fuel_storage( const itype_id &fuel ) } for( const bionic_id &bd : loaded_bio ) { - set_value( bd.c_str(), fuel ); + set_value( bd.str(), fuel.str() ); } } @@ -3173,13 +3187,13 @@ std::vector Character::get_overlay_ids() const // next clothing // TODO: worry about correct order of clothing overlays for( const item &worn_item : worn ) { - rval.push_back( "worn_" + worn_item.typeId() ); + rval.push_back( "worn_" + worn_item.typeId().str() ); } // last weapon // TODO: might there be clothing that covers the weapon? if( is_armed() ) { - rval.push_back( "wielded_" + weapon.typeId() ); + rval.push_back( "wielded_" + weapon.typeId().str() ); } if( move_mode != CMM_WALK ) { @@ -5293,7 +5307,7 @@ void Character::update_bodytemp() const bool has_bark = has_trait( trait_BARK ); const bool has_sleep = has_effect( effect_sleep ); const bool has_sleep_state = has_sleep || in_sleep_state(); - const bool has_heatsink = has_bionic( bio_heatsink ) || is_wearing( "rm13_armor_on" ) || + const bool has_heatsink = has_bionic( bio_heatsink ) || is_wearing( itype_rm13_armor_on ) || has_trait( trait_M_SKIN2 ) || has_trait( trait_M_SKIN3 ); const bool has_common_cold = has_effect( effect_common_cold ); const bool has_climate_control = in_climate_control(); @@ -6285,7 +6299,7 @@ bool Character::is_immune_field( const field_type_id &fid ) const return is_elec_immune(); } if( ft.has_fire ) { - return has_active_bionic( bio_heatsink ) || is_wearing( "rm13_armor_on" ); + return has_active_bionic( bio_heatsink ) || is_wearing( itype_rm13_armor_on ); } if( ft.has_acid ) { return !is_on_ground() && get_env_resist( bodypart_id( "foot_l" ) ) >= 15 && @@ -6315,7 +6329,7 @@ bool Character::is_immune_effect( const efftype_id &eff ) const } else if( eff == effect_deaf ) { return worn_with_flag( flag_DEAF ) || worn_with_flag( flag_PARTIAL_DEAF ) || has_bionic( bio_ears ) || - is_wearing( "rm13_armor_on" ); + is_wearing( itype_rm13_armor_on ); } else if( eff == effect_corroding ) { return is_immune_damage( DT_ACID ) || has_trait( trait_SLIMY ) || has_trait( trait_VISCOUS ); } else if( eff == effect_nausea ) { @@ -6664,7 +6678,7 @@ int Character::ammo_count_for( const item &gun ) int ups_drain = gun.get_gun_ups_drain(); if( ups_drain > 0 ) { - ret = std::min( ret, charges_of( "UPS" ) / ups_drain ); + ret = std::min( ret, charges_of( itype_UPS ) / ups_drain ); } return ret; @@ -7042,7 +7056,7 @@ units::mass Character::bionics_weight() const units::mass bio_weight = 0_gram; for( const bionic_id &bid : get_bionics() ) { if( !bid->included ) { - bio_weight += item::find_type( bid.c_str() )->weight; + bio_weight += item::find_type( bid->itype() )->weight; } } return bio_weight; @@ -7625,7 +7639,7 @@ bool Character::has_enough_charges( const item &it, bool show_msg ) const return true; } if( it.has_flag( flag_USE_UPS ) ) { - if( has_charges( "UPS", it.ammo_required() ) || it.ammo_sufficient() ) { + if( has_charges( itype_UPS, it.ammo_required() ) || it.ammo_sufficient() ) { return true; } if( show_msg ) { @@ -7688,7 +7702,7 @@ bool Character::consume_charges( item &used, int qty ) if( used.charges >= qty ) { used.ammo_consume( qty, pos() ); } else { - use_charges( "UPS", qty ); + use_charges( itype_UPS, qty ); } } else { used.ammo_consume( std::min( qty, used.ammo_remaining() ), pos() ); @@ -7704,7 +7718,7 @@ int Character::item_handling_cost( const item &it, bool penalties, int base_cost mv += std::min( 200, it.volume() / 20_ml ); } - if( weapon.typeId() == "e_handcuffs" ) { + if( weapon.typeId() == itype_e_handcuffs ) { mv *= 4; } else if( penalties && has_effect( effect_grabbed ) ) { mv *= 2; @@ -9410,7 +9424,7 @@ void Character::cancel_activity() } if( has_activity( ACT_LOCKPICK ) ) { std::vector bio_picklocks = g->u.items_with( []( const item & itm ) { - return itm.typeId() == "pseudo_bio_picklock"; + return itm.typeId() == itype_pseudo_bio_picklock; } ); if( !bio_picklocks.empty() ) { g->u.i_rem( bio_picklocks[0] ); @@ -9764,10 +9778,10 @@ std::vector Character::all_items_with_flag( const std::string &fla bool Character::has_charges( const itype_id &it, int quantity, const std::function &filter ) const { - if( it == "fire" || it == "apparatus" ) { + if( it == itype_fire || it == itype_apparatus ) { return has_fire( quantity ); } - if( it == "UPS" && is_mounted() && + if( it == itype_UPS && is_mounted() && mounted_creature.get()->has_flag( MF_RIDEABLE_MECH ) ) { auto mons = mounted_creature.get(); return quantity <= mons->battery_item->ammo_remaining(); @@ -9815,15 +9829,15 @@ std::list Character::use_charges( const itype_id &what, int qty, if( qty <= 0 ) { return res; - } else if( what == "toolset" ) { + } else if( what == itype_toolset ) { mod_power_level( units::from_kilojoule( -qty ) ); return res; - } else if( what == "fire" ) { + } else if( what == itype_fire ) { use_fire( qty ); return res; - } else if( what == "UPS" ) { + } else if( what == itype_UPS ) { if( is_mounted() && mounted_creature.get()->has_flag( MF_RIDEABLE_MECH ) && mounted_creature.get()->battery_item ) { auto mons = mounted_creature.get(); @@ -9838,16 +9852,16 @@ std::list Character::use_charges( const itype_id &what, int qty, qty -= std::min( qty, bio ); } - int adv = charges_of( "adv_UPS_off", static_cast( std::ceil( qty * 0.6 ) ) ); + int adv = charges_of( itype_adv_UPS_off, static_cast( std::ceil( qty * 0.6 ) ) ); if( adv > 0 ) { - std::list found = use_charges( "adv_UPS_off", adv ); + std::list found = use_charges( itype_adv_UPS_off, adv ); res.splice( res.end(), found ); qty -= std::min( qty, static_cast( adv / 0.6 ) ); } - int ups = charges_of( "UPS_off", qty ); + int ups = charges_of( itype_UPS_off, qty ); if( ups > 0 ) { - std::list found = use_charges( "UPS_off", ups ); + std::list found = use_charges( itype_UPS_off, ups ); res.splice( res.end(), found ); qty -= std::min( qty, ups ); } @@ -9872,7 +9886,7 @@ std::list Character::use_charges( const itype_id &what, int qty, } if( has_tool_with_UPS ) { - use_charges( "UPS", qty ); + use_charges( itype_UPS, qty ); } return res; @@ -10377,7 +10391,7 @@ void Character::place_corpse() g->m.add_item_or_charges( pos(), *itm ); } for( const bionic &bio : *my_bionics ) { - if( item::type_is_defined( bio.id.str() ) ) { + if( item::type_is_defined( bio.info().itype() ) ) { item cbm( bio.id.str(), calendar::turn ); cbm.set_flag( "FILTHY" ); cbm.set_flag( "NO_STERILE" ); @@ -10426,7 +10440,7 @@ void Character::place_corpse( const tripoint &om_target ) bay.add_item_or_charges( point( finX, finY ), *itm ); } for( const bionic &bio : *my_bionics ) { - if( item::type_is_defined( bio.id.str() ) ) { + if( item::type_is_defined( bio.info().itype() ) ) { body.put_in( item( bio.id.str(), calendar::turn ), item_pocket::pocket_type::CORPSE ); } } diff --git a/src/character_martial_arts.cpp b/src/character_martial_arts.cpp index 09af7aa18e3c7..9da3ee7c36eb6 100644 --- a/src/character_martial_arts.cpp +++ b/src/character_martial_arts.cpp @@ -13,8 +13,6 @@ static const matype_id style_kicks( "style_kicks" ); static const matype_id style_none( "style_none" ); -using itype_id = std::string; - character_martial_arts::character_martial_arts() { diff --git a/src/character_martial_arts.h b/src/character_martial_arts.h index 7ba9dbd213d27..104f62888acd2 100644 --- a/src/character_martial_arts.h +++ b/src/character_martial_arts.h @@ -15,8 +15,6 @@ class JsonOut; class avatar; class item; -using itype_id = std::string; - class character_martial_arts { private: diff --git a/src/clothing_mod.h b/src/clothing_mod.h index abf55e195c30c..2ee05a58fe5ce 100644 --- a/src/clothing_mod.h +++ b/src/clothing_mod.h @@ -49,7 +49,7 @@ struct clothing_mod { bool was_loaded = false; std::string flag; - std::string item_string; + itype_id item_string; std::string implement_prompt; std::string destroy_prompt; std::vector< mod_value > mod_values; diff --git a/src/clzones.cpp b/src/clzones.cpp index 1ccb844c69600..356834965f59e 100644 --- a/src/clzones.cpp +++ b/src/clzones.cpp @@ -271,10 +271,10 @@ plot_options::query_seed_result plot_options::query_seed() if( seed_index > 0 && seed_index < static_cast( seed_entries.size() ) ) { const auto &seed_entry = seed_entries[seed_index]; - const auto &new_seed = std::get<0>( seed_entry ); - std::string new_mark; + const itype_id &new_seed = std::get<0>( seed_entry ); + itype_id new_mark; - item it = item( itype_id( new_seed ) ); + item it = item( new_seed ); if( it.is_seed() ) { new_mark = it.type->seed->fruit_id; } else { @@ -290,9 +290,9 @@ plot_options::query_seed_result plot_options::query_seed() } } else if( seed_index == 0 ) { // No seeds - if( !seed.empty() || !mark.empty() ) { - seed.clear(); - mark.clear(); + if( !seed.is_empty() || !mark.is_empty() ) { + seed = itype_id(); + mark = itype_id(); return changed; } else { return successful; @@ -370,7 +370,7 @@ std::string blueprint_options::get_zone_name_suggestion() const std::string plot_options::get_zone_name_suggestion() const { - if( !seed.empty() ) { + if( !seed.is_empty() ) { auto type = itype_id( seed ); item it = item( type ); if( it.is_seed() ) { @@ -396,8 +396,9 @@ std::vector> blueprint_options::get_descript std::vector> plot_options::get_descriptions() const { auto options = std::vector>(); - options.emplace_back( std::make_pair( _( "Plant seed: " ), - !seed.empty() ? item::nname( itype_id( seed ) ) : _( "No seed" ) ) ); + options.emplace_back( + std::make_pair( _( "Plant seed: " ), + !seed.is_empty() ? item::nname( itype_id( seed ) ) : _( "No seed" ) ) ); return options; } diff --git a/src/clzones.h b/src/clzones.h index 2ca66fd5166dc..aee8d3b406376 100644 --- a/src/clzones.h +++ b/src/clzones.h @@ -111,8 +111,8 @@ class mark_option class plot_options : public zone_options, public mark_option { private: - std::string mark; - std::string seed; + itype_id mark; + itype_id seed; enum query_seed_result { canceled, @@ -124,9 +124,9 @@ class plot_options : public zone_options, public mark_option public: std::string get_mark() const override { - return mark; + return mark.str(); } - std::string get_seed() const { + itype_id get_seed() const { return seed; } diff --git a/src/computer_session.cpp b/src/computer_session.cpp index cde58011c12c6..9641fee58646b 100644 --- a/src/computer_session.cpp +++ b/src/computer_session.cpp @@ -58,6 +58,18 @@ static const efftype_id effect_amigara( "amigara" ); +static const itype_id itype_black_box( "black_box" ); +static const itype_id itype_blood( "blood" ); +static const itype_id itype_c4( "c4" ); +static const itype_id itype_cobalt_60( "cobalt_60" ); +static const itype_id itype_mininuke( "mininuke" ); +static const itype_id itype_mininuke_act( "mininuke_act" ); +static const itype_id itype_radio_repeater_mod( "radio_repeater_mod" ); +static const itype_id itype_sarcophagus_access_code( "sarcophagus_access_code" ); +static const itype_id itype_sewage( "sewage" ); +static const itype_id itype_usb_drive( "usb_drive" ); +static const itype_id itype_vacutainer( "vacutainer" ); + static const skill_id skill_computer( "computer" ); static const species_id HUMAN( "HUMAN" ); @@ -220,7 +232,7 @@ bool computer_session::hack_attempt( player &p, int Security ) static item *pick_usb() { auto filter = []( const item & it ) { - return it.typeId() == "usb_drive"; + return it.typeId() == itype_usb_drive; }; item_location loc = game_menus::inv::titled_filter_menu( filter, g->u, _( "Choose drive:" ) ); @@ -359,7 +371,7 @@ void computer_session::action_sample() continue; } bool found_item = false; - item sewage( "sewage", calendar::turn ); + item sewage( itype_sewage, calendar::turn ); for( item &elem : g->m.i_at( n ) ) { int capa = elem.get_remaining_capacity_for_liquid( sewage ); if( capa <= 0 ) { @@ -685,7 +697,7 @@ void computer_session::action_complete_disable_external_power() void computer_session::action_repeater_mod() { - if( g->u.has_amount( "radio_repeater_mod", 1 ) ) { + if( g->u.has_amount( itype_radio_repeater_mod, 1 ) ) { for( auto miss : g->u.get_active_missions() ) { static const mission_type_id commo_3 = mission_type_id( "MISSION_OLD_GUARD_NEC_COMMO_3" ), commo_4 = mission_type_id( "MISSION_OLD_GUARD_NEC_COMMO_4" ); @@ -693,7 +705,7 @@ void computer_session::action_repeater_mod() miss->step_complete( 1 ); print_error( _( "Repeater mod installed…" ) ); print_error( _( "Mission Complete!" ) ); - g->u.use_amount( "radio_repeater_mod", 1 ); + g->u.use_amount( itype_radio_repeater_mod, 1 ); query_any(); comp.options.clear(); activate_failure( COMPFAIL_SHUTDOWN ); @@ -738,7 +750,7 @@ void computer_session::action_blood_anal() print_error( _( "ERROR: Please remove all but one sample from centrifuge." ) ); } else if( items.only_item().contents.empty() ) { print_error( _( "ERROR: Please only use container with blood sample." ) ); - } else if( items.only_item().contents.legacy_front().typeId() != "blood" ) { + } else if( items.only_item().contents.legacy_front().typeId() != itype_blood ) { print_error( _( "ERROR: Please only use blood samples." ) ); } else { // Success! const item &blood = items.only_item().contents.legacy_front(); @@ -782,13 +794,14 @@ void computer_session::action_data_anal() print_error( _( "ERROR: Please place memory bank in scan area." ) ); } else if( items.size() > 1 ) { print_error( _( "ERROR: Please only scan one item at a time." ) ); - } else if( items.only_item().typeId() != "usb_drive" && - items.only_item().typeId() != "black_box" ) { + } else if( items.only_item().typeId() != itype_usb_drive && + items.only_item().typeId() != itype_black_box ) { print_error( _( "ERROR: Memory bank destroyed or not present." ) ); - } else if( items.only_item().typeId() == "usb_drive" && items.only_item().contents.empty() ) { + } else if( items.only_item().typeId() == itype_usb_drive && + items.only_item().contents.empty() ) { print_error( _( "ERROR: Memory bank is empty." ) ); } else { // Success! - if( items.only_item().typeId() == "black_box" ) { + if( items.only_item().typeId() == itype_black_box ) { print_line( _( "Memory Bank: Military Hexron Encryption\nPrinting Transcript\n" ) ); item transcript( "black_box_transcript", calendar::turn ); g->m.add_item_or_charges( g->u.pos(), transcript ); @@ -928,10 +941,10 @@ void computer_session::action_srcf_seal() void computer_session::action_srcf_elevator() { - if( !g->u.has_amount( "sarcophagus_access_code", 1 ) ) { + if( !g->u.has_amount( itype_sarcophagus_access_code, 1 ) ) { print_error( _( "Access code required!" ) ); } else { - g->u.use_amount( "sarcophagus_access_code", 1 ); + g->u.use_amount( itype_sarcophagus_access_code, 1 ); reset_terminal(); print_line( _( "\nPower: Backup Only\nRadiation Level: Very Dangerous\nOperational: Overridden\n\n" ) ); @@ -959,11 +972,13 @@ void computer_session::action_irradiator() g->u.moves -= 300; for( auto it = g->m.i_at( dest ).begin(); it != g->m.i_at( dest ).end(); ++it ) { // actual food processing - if( !it->rotten() && item_controller->has_template( "irradiated_" + it->typeId() ) ) { - it->convert( "irradiated_" + it->typeId() ); + itype_id irradiated_type( "irradiated_" + it->typeId().str() ); + if( !it->rotten() && item_controller->has_template( irradiated_type ) ) { + it->convert( irradiated_type ); } // critical failure - radiation spike sets off electronic detonators - if( it->typeId() == "mininuke" || it->typeId() == "mininuke_act" || it->typeId() == "c4" ) { + if( it->typeId() == itype_mininuke || it->typeId() == itype_mininuke_act || + it->typeId() == itype_c4 ) { explosion_handler::explosion( dest, 40 ); reset_terminal(); print_error( _( "WARNING [409]: Primary sensors offline!" ) ); @@ -1134,7 +1149,7 @@ void computer_session::action_extract_rad_source() } } if( p_exists ) { - g->m.spawn_item( platform, "cobalt_60", rng( 8, 15 ) ); + g->m.spawn_item( platform, itype_cobalt_60, rng( 8, 15 ) ); g->m.translate_radius( t_rad_platform, t_concrete, 8.0, g->u.pos(), true ); comp.remove_option( COMPACT_IRRADIATOR ); comp.remove_option( COMPACT_EXTRACT_RAD_SOURCE ); @@ -1338,11 +1353,11 @@ void computer_session::failure_destroy_blood() print_error( _( "ERROR: Please place sample in centrifuge." ) ); } else if( items.size() > 1 ) { print_error( _( "ERROR: Please remove all but one sample from centrifuge." ) ); - } else if( items.only_item().typeId() != "vacutainer" ) { + } else if( items.only_item().typeId() != itype_vacutainer ) { print_error( _( "ERROR: Please use blood-contained samples." ) ); } else if( items.only_item().contents.empty() ) { print_error( _( "ERROR: Blood draw kit, empty." ) ); - } else if( items.only_item().contents.legacy_front().typeId() != "blood" ) { + } else if( items.only_item().contents.legacy_front().typeId() != itype_blood ) { print_error( _( "ERROR: Please only use blood samples." ) ); } else { print_error( _( "ERROR: Blood sample destroyed." ) ); @@ -1363,7 +1378,7 @@ void computer_session::failure_destroy_data() print_error( _( "ERROR: Please place memory bank in scan area." ) ); } else if( items.size() > 1 ) { print_error( _( "ERROR: Please only scan one item at a time." ) ); - } else if( items.only_item().typeId() != "usb_drive" ) { + } else if( items.only_item().typeId() != itype_usb_drive ) { print_error( _( "ERROR: Memory bank destroyed or not present." ) ); } else if( items.only_item().contents.empty() ) { print_error( _( "ERROR: Memory bank is empty." ) ); diff --git a/src/condition.cpp b/src/condition.cpp index 51460ce658179..82448460bec55 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -245,7 +245,7 @@ template void conditional_t::set_is_wearing( const JsonObject &jo, const std::string &member, bool is_npc ) { - const std::string &item_id = jo.get_string( member ); + const itype_id item_id( jo.get_string( member ) ); condition = [item_id, is_npc]( const T & d ) { player *actor = d.alpha; if( is_npc ) { @@ -258,7 +258,7 @@ void conditional_t::set_is_wearing( const JsonObject &jo, const std::string & template void conditional_t::set_has_item( const JsonObject &jo, const std::string &member, bool is_npc ) { - const std::string &item_id = jo.get_string( member ); + const itype_id item_id( jo.get_string( member ) ); condition = [item_id, is_npc]( const T & d ) { player *actor = d.alpha; if( is_npc ) { @@ -277,7 +277,7 @@ void conditional_t::set_has_items( const JsonObject &jo, const std::string &m return false; }; } else { - const std::string item_id = has_items.get_string( "item" ); + const itype_id item_id( has_items.get_string( "item" ) ); int count = has_items.get_int( "count" ); condition = [item_id, count, is_npc]( const T & d ) { player *actor = d.alpha; diff --git a/src/construction.cpp b/src/construction.cpp index d87c60a758fa3..06ecea6415a07 100644 --- a/src/construction.cpp +++ b/src/construction.cpp @@ -64,6 +64,12 @@ static const construction_category_id construction_category_ALL( "ALL" ); static const construction_category_id construction_category_FILTER( "FILTER" ); static const construction_category_id construction_category_REPAIR( "REPAIR" ); +static const itype_id itype_2x4( "2x4" ); +static const itype_id itype_nail( "nail" ); +static const itype_id itype_sheet( "sheet" ); +static const itype_id itype_stick( "stick" ); +static const itype_id itype_string_36( "string_36" ); + static const trap_str_id tr_firewood_source( "tr_firewood_source" ); static const trap_str_id tr_practice_target( "tr_practice_target" ); static const trap_str_id tr_unfinished_construction( "tr_unfinished_construction" ); @@ -1153,7 +1159,7 @@ void construct::done_grave( const tripoint &p ) g->m.destroy_furn( p, true ); } -static vpart_id vpart_from_item( const std::string &item_id ) +static vpart_id vpart_from_item( const itype_id &item_id ) { for( const auto &e : vpart_info::all() ) { const vpart_info &vp = e.second; @@ -1257,7 +1263,7 @@ static void unroll_digging( const int numer_of_2x4s ) item rope( "rope_30" ); g->m.add_item_or_charges( g->u.pos(), rope ); // presuming 2x4 to conserve lumber. - g->m.spawn_item( g->u.pos(), "2x4", numer_of_2x4s ); + g->m.spawn_item( g->u.pos(), itype_2x4, numer_of_2x4s ); } void construct::done_digormine_stair( const tripoint &p, bool dig ) @@ -1360,10 +1366,10 @@ void construct::done_wood_stairs( const tripoint &p ) void construct::done_window_curtains( const tripoint & ) { // copied from iexamine::curtains - g->m.spawn_item( g->u.pos(), "nail", 1, 4 ); - g->m.spawn_item( g->u.pos(), "sheet", 2 ); - g->m.spawn_item( g->u.pos(), "stick" ); - g->m.spawn_item( g->u.pos(), "string_36" ); + g->m.spawn_item( g->u.pos(), itype_nail, 1, 4 ); + g->m.spawn_item( g->u.pos(), itype_sheet, 2 ); + g->m.spawn_item( g->u.pos(), itype_stick ); + g->m.spawn_item( g->u.pos(), itype_string_36 ); g->u.add_msg_if_player( _( "After boarding up the window the curtains and curtain rod are left." ) ); } diff --git a/src/consumption.cpp b/src/consumption.cpp index d42e450594a50..b9e57de51fc2e 100644 --- a/src/consumption.cpp +++ b/src/consumption.cpp @@ -74,6 +74,10 @@ static const efftype_id effect_visuals( "visuals" ); static const item_category_id item_category_chems( "chems" ); +static const itype_id itype_apparatus( "dab_pen_on" ); +static const itype_id itype_dab_pen_on( "dab_pen_on" ); +static const itype_id itype_syringe( "syringe" ); + static const trait_id trait_ACIDBLOOD( "ACIDBLOOD" ); static const trait_id trait_AMORPHOUS( "AMORPHOUS" ); static const trait_id trait_ANTIFRUIT( "ANTIFRUIT" ); @@ -176,9 +180,9 @@ const units::volume furnace_max_volume( 3_liter ); // TODO: JSONize. const std::map plut_charges = { - { "plut_cell", PLUTONIUM_CHARGES * 10 }, - { "plut_slurry_dense", PLUTONIUM_CHARGES }, - { "plut_slurry", PLUTONIUM_CHARGES / 2 } + { itype_id( "plut_cell" ), PLUTONIUM_CHARGES * 10 }, + { itype_id( "plut_slurry_dense" ), PLUTONIUM_CHARGES }, + { itype_id( "plut_slurry" ), PLUTONIUM_CHARGES / 2 } }; int Character::stomach_capacity() const @@ -409,7 +413,7 @@ std::pair Character::compute_nutrient_range( } if( result_it.typeId() != comest_it.typeId() ) { debugmsg( "When creating recipe result expected %s, got %s\n", - comest_it.typeId(), result_it.typeId() ); + comest_it.typeId().str(), result_it.typeId().str() ); } std::tie( this_min, this_max ) = compute_nutrient_range( result_it, rec, extra_flags ); min_nutr.min_in_place( this_min ); @@ -689,7 +693,7 @@ ret_val Character::can_eat( const item &food ) const } } - if( comest->tool != "null" ) { + if( !comest->tool.is_null() ) { const bool has = item::count_by_charges( comest->tool ) ? has_charges( comest->tool, 1 ) : has_amount( comest->tool, 1 ); @@ -1497,7 +1501,7 @@ bool Character::fuel_bionic_with( item &it ) const bionic_id bio = get_most_efficient_bionic( get_bionic_fueled_with( it ) ); const int loadable = std::min( it.charges, get_fuel_capacity( it.typeId() ) ); - const std::string str_loaded = get_value( it.typeId() ); + const std::string str_loaded = get_value( it.typeId().str() ); int loaded = 0; if( !str_loaded.empty() ) { loaded = std::stoi( str_loaded ); @@ -1507,7 +1511,7 @@ bool Character::fuel_bionic_with( item &it ) it.charges -= loadable; // Type and amount of fuel - set_value( it.typeId(), new_charge ); + set_value( it.typeId().str(), new_charge ); update_fuel_storage( it.typeId() ); add_msg_player_or_npc( m_info, //~ %1$i: charge number, %2$s: item name, %3$s: bionics name @@ -1658,11 +1662,11 @@ time_duration Character::get_consume_time( const item &it ) if( consume_drug != nullptr ) { //its a drug const auto consume_drug_use = dynamic_cast ( consume_drug->get_actor_ptr() ); - if( consume_drug_use->tools_needed.find( "syringe" ) != consume_drug_use->tools_needed.end() ) { + if( consume_drug_use->tools_needed.find( itype_syringe ) != consume_drug_use->tools_needed.end() ) { time = time_duration::from_minutes( 5 );//sterile injections take 5 minutes - } else if( consume_drug_use->tools_needed.find( "apparatus" ) != + } else if( consume_drug_use->tools_needed.find( itype_apparatus ) != consume_drug_use->tools_needed.end() || - consume_drug_use->tools_needed.find( "dab_pen_on" ) != consume_drug_use->tools_needed.end() ) { + consume_drug_use->tools_needed.find( itype_dab_pen_on ) != consume_drug_use->tools_needed.end() ) { time = time_duration::from_seconds( 30 );//smoke a bowl } else { time = time_duration::from_seconds( 5 );//popping a pill is quick @@ -1725,7 +1729,7 @@ static bool consume_med( item &target, player &you ) const itype_id tool_type = target.get_comestible()->tool; const auto req_tool = item::find_type( tool_type ); bool tool_override = false; - if( tool_type == "syringe" && you.has_bionic( bio_syringe ) ) { + if( tool_type == itype_syringe && you.has_bionic( bio_syringe ) ) { tool_override = true; } if( req_tool->tool ) { diff --git a/src/craft_command.h b/src/craft_command.h index 17f345394dd3c..1c70f8b14d8f0 100644 --- a/src/craft_command.h +++ b/src/craft_command.h @@ -37,7 +37,7 @@ struct enum_traits { /** * Struct that represents a selection of a component for crafting. */ -template +template struct comp_selection { /** Tells us where the selected component should be used from. */ usage use_from = use_from_none; diff --git a/src/crafting.cpp b/src/crafting.cpp index d05ecb096a4b1..08f74591d234b 100644 --- a/src/crafting.cpp +++ b/src/crafting.cpp @@ -80,6 +80,8 @@ static const activity_id ACT_DISASSEMBLE( "ACT_DISASSEMBLE" ); static const efftype_id effect_contacts( "contacts" ); +static const itype_id itype_plut_cell( "plut_cell" ); + static const skill_id skill_electronics( "electronics" ); static const skill_id skill_tailor( "tailor" ); @@ -548,7 +550,7 @@ const inventory &Character::crafting_inventory( const tripoint &src_pos, int rad for( const bionic &bio : *my_bionics ) { const bionic_data &bio_data = bio.info(); if( ( !bio_data.activated || bio.powered ) && - !bio_data.fake_item.empty() ) { + !bio_data.fake_item.is_empty() ) { cached_crafting_inventory += item( bio.info().fake_item, calendar::turn, units::to_kilojoule( get_power_level() ) ); } @@ -1155,7 +1157,7 @@ void player::complete_craft( item &craft, const tripoint &loc ) // if a component item has "cooks_like" it will be replaced by that item as a component for( item &comp : used ) { // only comestibles have cooks_like. any other type of item will throw an exception, so filter those out - if( comp.is_comestible() && !comp.get_comestible()->cooks_like.empty() ) { + if( comp.is_comestible() && !comp.get_comestible()->cooks_like.is_empty() ) { comp = item( comp.get_comestible()->cooks_like, comp.birthday(), comp.charges ); } // If this recipe is cooked, components are no longer raw. @@ -2060,7 +2062,7 @@ bool player::disassemble( item_location target, bool interactive ) // index is used as a bool that indicates if we want recursive uncraft. activity.index = false; activity.targets.emplace_back( std::move( target ) ); - activity.str_values.push_back( r.result() ); + activity.str_values.push_back( r.result().str() ); // Unused position attribute used to store ammo to disassemble activity.position = std::min( num_dis, obj.charges ); @@ -2102,7 +2104,7 @@ void player::complete_disassemble() // Disassembly has 2 parallel vectors: // item location, and recipe id - const recipe &rec = recipe_dictionary::get_uncraft( activity.str_values.back() ); + const recipe &rec = recipe_dictionary::get_uncraft( itype_id( activity.str_values.back() ) ); if( rec ) { complete_disassemble( activity.targets.back(), rec ); @@ -2129,7 +2131,8 @@ void player::complete_disassemble() } // Set get and set duration of next uncraft - const recipe &next_recipe = recipe_dictionary::get_uncraft( activity.str_values.back() ); + const recipe &next_recipe = recipe_dictionary::get_uncraft( itype_id( + activity.str_values.back() ) ); if( !next_recipe ) { debugmsg( "bad disassembly recipe: %d", activity.str_values.back() ); @@ -2346,16 +2349,16 @@ void remove_ammo( item &dis_item, player &p ) if( dis_item.has_flag( flag_NO_UNLOAD ) ) { return; } - if( dis_item.is_gun() && dis_item.ammo_current() != "null" ) { + if( dis_item.is_gun() && !dis_item.ammo_current().is_null() ) { item ammodrop( dis_item.ammo_current(), calendar::turn ); ammodrop.charges = dis_item.charges; drop_or_handle( ammodrop, p ); dis_item.charges = 0; } - if( dis_item.is_tool() && dis_item.charges > 0 && dis_item.ammo_current() != "null" ) { + if( dis_item.is_tool() && dis_item.charges > 0 && !dis_item.ammo_current().is_null() ) { item ammodrop( dis_item.ammo_current(), calendar::turn ); ammodrop.charges = dis_item.charges; - if( dis_item.ammo_current() == "plut_cell" ) { + if( dis_item.ammo_current() == itype_plut_cell ) { ammodrop.charges /= PLUTONIUM_CHARGES; } drop_or_handle( ammodrop, p ); diff --git a/src/crafting_gui.cpp b/src/crafting_gui.cpp index e0d5a837c5bb2..67828168ab7f5 100644 --- a/src/crafting_gui.cpp +++ b/src/crafting_gui.cpp @@ -929,8 +929,8 @@ const recipe *select_crafting_recipe( int &batch_size ) std::string peek_related_recipe( const recipe *current, const recipe_subset &available ) { auto compare_second = - []( const std::pair &a, - const std::pair &b ) { + []( const std::pair &a, + const std::pair &b ) { return localized_compare( a.second, b.second ); }; diff --git a/src/debug_menu.cpp b/src/debug_menu.cpp index 4c34d0cd6b9de..8b7ad6fd60b81 100644 --- a/src/debug_menu.cpp +++ b/src/debug_menu.cpp @@ -476,7 +476,8 @@ void character_edit_menu() data << np->myclass.obj().get_name() << "; " << npc_attitude_name( np->get_attitude() ) << "; " << ( np->get_faction() ? np->get_faction()->name : _( "no faction" ) ) << "; " << - ( np->get_faction() ? np->get_faction()->currency : _( "no currency" ) ) << "; " << + ( np->get_faction() ? np->get_faction()->currency->nname( 1 ) : _( "no currency" ) ) + << "; " << "api: " << np->get_faction_ver() << std::endl; if( np->has_destination() ) { data << string_format( _( "Destination: %d:%d:%d (%s)" ), diff --git a/src/dialogue.h b/src/dialogue.h index 831e47ee57c12..3cdf4b200e1e6 100644 --- a/src/dialogue.h +++ b/src/dialogue.h @@ -75,7 +75,7 @@ struct talk_topic { std::string id; /** If we're talking about an item, this should be its type. */ - itype_id item_type = "null"; + itype_id item_type = itype_id::NULL_ID(); /** Reason for denying a request. */ std::string reason; }; @@ -83,7 +83,7 @@ struct talk_topic { struct talk_effect_fun_t { private: std::function function; - std::vector> likely_rewards; + std::vector> likely_rewards; public: talk_effect_fun_t() = default; @@ -98,10 +98,10 @@ struct talk_effect_fun_t { void set_add_var( const JsonObject &jo, const std::string &member, bool is_npc = false ); void set_remove_var( const JsonObject &jo, const std::string &member, bool is_npc = false ); void set_adjust_var( const JsonObject &jo, const std::string &member, bool is_npc = false ); - void set_u_buy_item( const std::string &item_name, int cost, int count, + void set_u_buy_item( const itype_id &item_name, int cost, int count, const std::string &container_name ); void set_u_spend_cash( int amount ); - void set_u_sell_item( const std::string &item_name, int cost, int count ); + void set_u_sell_item( const itype_id &item_name, int cost, int count ); void set_consume_item( const JsonObject &jo, const std::string &member, int count, bool is_npc = false ); void set_remove_item_with( const JsonObject &jo, const std::string &member, bool is_npc = false ); @@ -120,7 +120,7 @@ struct talk_effect_fun_t { void set_bulk_trade_accept( bool is_trade, bool is_npc = false ); void set_npc_gets_item( bool to_use ); void set_add_mission( const std::string &mission_id ); - const std::vector> &get_likely_rewards() const; + const std::vector> &get_likely_rewards() const; void set_u_buy_monster( const std::string &monster_type_id, int cost, int count, bool pacified, const translation &name ); void set_u_learn_recipe( const std::string &learned_recipe_id ); @@ -381,7 +381,7 @@ class json_talk_repeat_response json_talk_repeat_response( const JsonObject &jo ); bool is_npc = false; bool include_containers = false; - std::vector for_item; + std::vector for_item; std::vector for_category; json_talk_response response; }; diff --git a/src/dump.cpp b/src/dump.cpp index 196b55f1c4484..32898a9be129c 100644 --- a/src/dump.cpp +++ b/src/dump.cpp @@ -54,22 +54,26 @@ bool game::dump_stats( const std::string &what, dump_mode mode, int scol = 0; // sorting column std::map test_npcs; - test_npcs[ "S1" ] = standard_npc( "S1", { 0, 0, 2 }, { "gloves_survivor", "mask_lsurvivor" }, - 4, 8, 10, 8, 10 /* DEX 10, PER 10 */ ); - test_npcs[ "S2" ] = standard_npc( "S2", { 0, 0, 3 }, { "gloves_fingerless", "sunglasses" }, - 4, 8, 8, 8, 10 /* PER 10 */ ); - test_npcs[ "S3" ] = standard_npc( "S3", { 0, 0, 4 }, { "gloves_plate", "helmet_plate" }, - 4, 10, 8, 8, 8 /* STAT 10 */ ); + test_npcs[ "S1" ] = standard_npc( + "S1", { 0, 0, 2 }, { "gloves_survivor", "mask_lsurvivor" }, + 4, 8, 10, 8, 10 /* DEX 10, PER 10 */ ); + test_npcs[ "S2" ] = standard_npc( + "S2", { 0, 0, 3 }, { "gloves_fingerless", "sunglasses" }, + 4, 8, 8, 8, 10 /* PER 10 */ ); + test_npcs[ "S3" ] = standard_npc( + "S3", { 0, 0, 4 }, { "gloves_plate", "helmet_plate" }, + 4, 10, 8, 8, 8 /* STAT 10 */ ); test_npcs[ "S4" ] = standard_npc( "S4", { 0, 0, 5 }, {}, 0, 8, 10, 8, 10 /* DEX 10, PER 10 */ ); test_npcs[ "S5" ] = standard_npc( "S5", { 0, 0, 6 }, {}, 4, 8, 10, 8, 10 /* DEX 10, PER 10 */ ); - test_npcs[ "S6" ] = standard_npc( "S6", { 0, 0, 7 }, { "gloves_hsurvivor", "mask_hsurvivor" }, - 4, 8, 10, 8, 10 /* DEX 10, PER 10 */ ); + test_npcs[ "S6" ] = standard_npc( + "S6", { 0, 0, 7 }, { "gloves_hsurvivor", "mask_hsurvivor" }, + 4, 8, 10, 8, 10 /* DEX 10, PER 10 */ ); std::map test_items; - test_items[ "G1" ] = item( "glock_19" ).ammo_set( "9mm" ); - test_items[ "G2" ] = item( "hk_mp5" ).ammo_set( "9mm" ); - test_items[ "G3" ] = item( "ar15" ).ammo_set( "223" ); - test_items[ "G4" ] = item( "remington_700" ).ammo_set( "270" ); + test_items[ "G1" ] = item( "glock_19" ).ammo_set( itype_id( "9mm" ) ); + test_items[ "G2" ] = item( "hk_mp5" ).ammo_set( itype_id( "9mm" ) ); + test_items[ "G3" ] = item( "ar15" ).ammo_set( itype_id( "223" ) ); + test_items[ "G4" ] = item( "remington_700" ).ammo_set( itype_id( "270" ) ); test_items[ "G4" ].put_in( item( "rifle_scope" ), item_pocket::pocket_type::MOD ); if( what == "AMMO" ) { diff --git a/src/editmap.cpp b/src/editmap.cpp index 5991cbb6ce1df..96c60c045977c 100644 --- a/src/editmap.cpp +++ b/src/editmap.cpp @@ -594,7 +594,8 @@ void editmap::update_view_with_help( const std::string &txt, const std::string & g->draw_item_override( map_p, itm.typeId(), mon ? mon->id : mtype_id::NULL_ID(), tile.get_item_count() > 1 ); } else { - g->draw_item_override( map_p, "null", mtype_id::NULL_ID(), false ); + g->draw_item_override( map_p, itype_id::NULL_ID(), mtype_id::NULL_ID(), + false ); } const optional_vpart_position vp = tmpmap.veh_at( tmp_p ); if( vp ) { diff --git a/src/effect.cpp b/src/effect.cpp index 9aaa4028f3d4c..b2ee1f26c33a3 100644 --- a/src/effect.cpp +++ b/src/effect.cpp @@ -31,6 +31,9 @@ static const efftype_id effect_tied( "tied" ); static const efftype_id effect_webbed( "webbed" ); static const efftype_id effect_weed_high( "weed_high" ); +static const itype_id itype_holybook_bible( "holybook_bible" ); +static const itype_id itype_money_bundle( "money_bundle" ); + static const trait_id trait_LACTOSE( "LACTOSE" ); static const trait_id trait_VEGETARIAN( "VEGETARIAN" ); @@ -103,7 +106,7 @@ void weed_msg( player &p ) } return; case 4: - if( p.has_amount( "money_bundle", 1 ) ) { // Half Baked + if( p.has_amount( itype_money_bundle, 1 ) ) { // Half Baked p.add_msg_if_player( _( "You ever see the back of a twenty dollar bill… on weed?" ) ); if( one_in( 2 ) ) { p.add_msg_if_player( @@ -112,7 +115,7 @@ void weed_msg( player &p ) p.add_msg_if_player( _( "RED TEAM GO, RED TEAM GO!" ) ); } } - } else if( p.has_amount( "holybook_bible", 1 ) ) { + } else if( p.has_amount( itype_holybook_bible, 1 ) ) { p.add_msg_if_player( _( "You have a sudden urge to flip your bible open to Genesis 1:29…" ) ); } else { // Big Lebowski p.add_msg_if_player( _( "That rug really tied the room together…" ) ); diff --git a/src/event.h b/src/event.h index 60e582c2e30c0..45524417a3a25 100644 --- a/src/event.h +++ b/src/event.h @@ -17,8 +17,6 @@ template struct enum_traits; -using itype_id = std::string; - // An event is something to be passed via the event_bus to subscribers // interested in being notified about events. // diff --git a/src/explosion.cpp b/src/explosion.cpp index 475ceb7bc34f4..41b920d7c2714 100644 --- a/src/explosion.cpp +++ b/src/explosion.cpp @@ -69,6 +69,10 @@ static const std::string flag_FLASH_PROTECTION( "FLASH_PROTECTION" ); static const itype_id fuel_type_none( "null" ); +static const itype_id itype_battery( "battery" ); +static const itype_id itype_e_handcuffs( "e_handcuffs" ); +static const itype_id itype_rm13_armor_on( "rm13_armor_on" ); + static const species_id ROBOT( "ROBOT" ); static const trait_id trait_LEG_TENT_BRACE( "LEG_TENT_BRACE" ); @@ -515,7 +519,7 @@ void explosion( const tripoint &p, const explosion_data &ex ) auto shrapnel_locations = shrapnel( p, ex.power, shr.casing_mass, shr.fragment_mass ); // If explosion drops shrapnel... - if( shr.recovery > 0 && shr.drop != "null" ) { + if( shr.recovery > 0 && !shr.drop.is_null() ) { // Extract only passable tiles affected by shrapnel std::vector tiles; @@ -543,7 +547,7 @@ void flashbang( const tripoint &p, bool player_immune ) draw_explosion( p, 8, c_white ); int dist = rl_dist( g->u.pos(), p ); if( dist <= 8 && !player_immune ) { - if( !g->u.has_bionic( bio_ears ) && !g->u.is_wearing( "rm13_armor_on" ) ) { + if( !g->u.has_bionic( bio_ears ) && !g->u.is_wearing( itype_rm13_armor_on ) ) { g->u.add_effect( effect_deaf, time_duration::from_turns( 40 - dist * 4 ) ); } if( g->m.sees( g->u.pos(), p, 8 ) ) { @@ -555,7 +559,7 @@ void flashbang( const tripoint &p, bool player_immune ) } else if( g->u.has_trait( trait_PER_SLIME_OK ) ) { flash_mod = 8; // Just retract those and extrude fresh eyes } else if( g->u.has_bionic( bio_sunglasses ) || - g->u.is_wearing( "rm13_armor_on" ) ) { + g->u.is_wearing( itype_rm13_armor_on ) ) { flash_mod = 6; } else if( g->u.worn_with_flag( flag_BLIND ) || g->u.worn_with_flag( flag_FLASH_PROTECTION ) ) { flash_mod = 3; // Not really proper flash protection, but better than nothing @@ -691,7 +695,7 @@ void emp_blast( const tripoint &p ) // Maybe export this to json? break; } - if( !mon_item_id.empty() && deact_chance != 0 && one_in( deact_chance ) ) { + if( !mon_item_id.is_empty() && deact_chance != 0 && one_in( deact_chance ) ) { if( sight ) { add_msg( _( "The %s beeps erratically and deactivates!" ), critter.name() ); } @@ -739,7 +743,7 @@ void emp_blast( const tripoint &p ) } // TODO: More effects? //e-handcuffs effects - if( g->u.weapon.typeId() == "e_handcuffs" && g->u.weapon.charges > 0 ) { + if( g->u.weapon.typeId() == itype_e_handcuffs && g->u.weapon.charges > 0 ) { g->u.weapon.item_tags.erase( "NO_UNWIELD" ); g->u.weapon.charges = 0; g->u.weapon.active = false; @@ -749,7 +753,7 @@ void emp_blast( const tripoint &p ) } // Drain any items of their battery charge for( auto &it : g->m.i_at( point( x, y ) ) ) { - if( it.is_tool() && it.ammo_current() == "battery" ) { + if( it.is_tool() && it.ammo_current() == itype_battery ) { it.charges = 0; } } diff --git a/src/explosion.h b/src/explosion.h index c24d5f2087051..b13cbc74ef740 100644 --- a/src/explosion.h +++ b/src/explosion.h @@ -5,7 +5,7 @@ #include #include -using itype_id = std::string; +#include "type_id.h" struct tripoint; class JsonObject; @@ -16,11 +16,11 @@ struct shrapnel_data { float fragment_mass = 0.005; // Percentage int recovery = 0; - itype_id drop = "null"; + itype_id drop = itype_id::NULL_ID(); shrapnel_data() = default; shrapnel_data( int casing_mass, float fragment_mass = 0.005, int recovery = 0, - itype_id drop = "null" ) + itype_id drop = itype_id::NULL_ID() ) : casing_mass( casing_mass ) , fragment_mass( fragment_mass ) , recovery( recovery ) diff --git a/src/faction.cpp b/src/faction.cpp index 92125923ad090..b93c6a5af9ae4 100644 --- a/src/faction.cpp +++ b/src/faction.cpp @@ -49,7 +49,7 @@ faction_template::faction_template() size = 0; power = 0; lone_wolf_faction = false; - currency = "null"; + currency = itype_id::NULL_ID(); } faction::faction( const faction_template &templ ) @@ -106,9 +106,9 @@ faction_template::faction_template( const JsonObject &jsobj ) , wealth( jsobj.get_int( "wealth" ) ) { if( jsobj.has_string( "currency" ) ) { - currency = jsobj.get_string( "currency" ); + jsobj.read( "currency", currency, true ); } else { - currency = "null"; + currency = itype_id::NULL_ID(); } lone_wolf_faction = jsobj.get_bool( "lone_wolf_faction", false ); load_relations( jsobj ); diff --git a/src/faction.h b/src/faction.h index 9c9f2ae1ac506..fef4dbc5845aa 100644 --- a/src/faction.h +++ b/src/faction.h @@ -85,7 +85,7 @@ class faction_template int food_supply; //Total nutritional value held int wealth; //Total trade currency bool lone_wolf_faction; // is this a faction for just one person? - std::string currency; // itype_id of the faction currency + itype_id currency; // id of the faction currency std::map> relations; std::string mon_faction; // mon_faction_id of the monster faction; defaults to human std::set> epilogue_data; diff --git a/src/faction_camp.cpp b/src/faction_camp.cpp index 4bc0114ba3044..1b49cdb3d5e03 100644 --- a/src/faction_camp.cpp +++ b/src/faction_camp.cpp @@ -82,6 +82,10 @@ class character_id; static const activity_id ACT_MOVE_LOOT( "ACT_MOVE_LOOT" ); +static const itype_id itype_fungal_seeds( "fungal_seeds" ); +static const itype_id itype_log( "log" ); +static const itype_id itype_marloss_seed( "marloss_seed" ); + static const std::string flag_PLOWABLE( "PLOWABLE" ); static const std::string flag_TREE( "TREE" ); @@ -2268,7 +2272,7 @@ void basecamp::start_crafting( const std::string &cur_id, const point &cur_dir, static bool farm_valid_seed( const item &itm ) { - return itm.is_seed() && itm.typeId() != "marloss_seed" && itm.typeId() != "fungal_seeds"; + return itm.is_seed() && itm.typeId() != itype_marloss_seed && itm.typeId() != itype_fungal_seeds; } static std::pair farm_action( const tripoint &omt_tgt, farm_ops op, @@ -3252,7 +3256,7 @@ int om_cutdown_trees( const tripoint &omt_tgt, int chance, bool estimate, bool f for( const tripoint &p : target_bay.points_in_rectangle( mapmin, mapmax ) ) { if( target_bay.ter( p ) == ter_id( "t_trunk" ) ) { target_bay.ter_set( p, t_dirt ); - target_bay.spawn_item( p, "log", rng( 2, 3 ), 0, calendar::turn ); + target_bay.spawn_item( p, itype_log, rng( 2, 3 ), 0, calendar::turn ); harvested++; } } diff --git a/src/game.cpp b/src/game.cpp index 5aa4b6cec6c93..4ee7359556b8b 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -226,6 +226,17 @@ static const efftype_id effect_winded( "winded" ); static const bionic_id bio_remote( "bio_remote" ); +static const itype_id itype_battery( "battery" ); +static const itype_id itype_grapnel( "grapnel" ); +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 itype_id itype_manhole_cover( "manhole_cover" ); +static const itype_id itype_remotevehcontrol( "remotevehcontrol" ); +static const itype_id itype_rm13_armor_on( "rm13_armor_on" ); +static const itype_id itype_rope_30( "rope_30" ); +static const itype_id itype_swim_fins( "swim_fins" ); + static const trait_id trait_BADKNEES( "BADKNEES" ); static const trait_id trait_ILLITERATE( "ILLITERATE" ); static const trait_id trait_INFIMMUNE( "INFIMMUNE" ); @@ -1049,8 +1060,8 @@ bool game::cleanup_at_end() int iNameLine = 0; int iInfoLine = 0; - if( u.has_amount( "holybook_bible1", 1 ) || u.has_amount( "holybook_bible2", 1 ) || - u.has_amount( "holybook_bible3", 1 ) ) { + 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_id( "CANNIBAL" ) ) || u.has_trait( trait_id( "PSYCHOPATH" ) ) ) ) { vRip.emplace_back( " _______ ___" ); vRip.emplace_back( " < `/ |" ); @@ -2571,13 +2582,13 @@ vehicle *game::remoteveh() remoteveh_cache_time = calendar::turn; std::stringstream remote_veh_string( u.get_value( "remote_controlling_vehicle" ) ); if( remote_veh_string.str().empty() || - ( !u.has_active_bionic( bio_remote ) && !u.has_active_item( "remotevehcontrol" ) ) ) { + ( !u.has_active_bionic( bio_remote ) && !u.has_active_item( itype_remotevehcontrol ) ) ) { remoteveh_cache = nullptr; } else { tripoint vp; remote_veh_string >> vp.x >> vp.y >> vp.z; vehicle *veh = veh_pointer_or_null( m.veh_at( vp ) ); - if( veh && veh->fuel_left( "battery", true ) > 0 ) { + if( veh && veh->fuel_left( itype_battery, true ) > 0 ) { remoteveh_cache = veh; } else { remoteveh_cache = nullptr; @@ -2591,7 +2602,7 @@ void game::setremoteveh( vehicle *veh ) remoteveh_cache_time = calendar::turn; remoteveh_cache = veh; if( veh != nullptr && !u.has_active_bionic( bio_remote ) && - !u.has_active_item( "remotevehcontrol" ) ) { + !u.has_active_item( itype_remotevehcontrol ) ) { debugmsg( "Tried to set remote vehicle without bio_remote or remotevehcontrol" ); veh = nullptr; } @@ -6477,7 +6488,7 @@ void game::zones_manager() if( !maybe_name.has_value() ) { break; } - const itype_id &name = maybe_name.value(); + const std::string &name = maybe_name.value(); const auto position = query_position(); if( !position ) { @@ -8895,7 +8906,7 @@ bool game::disable_robot( const tripoint &p ) } const auto mid = critter.type->id; const auto mon_item_id = critter.type->revert_to_itype; - if( !mon_item_id.empty() && + if( !mon_item_id.is_empty() && query_yn( _( "Deactivate the %s?" ), critter.name() ) ) { u.moves -= 100; @@ -9254,7 +9265,7 @@ bool game::walk_move( const tripoint &dest_loc ) int volume = u.is_stealthy() ? 3 : 6; volume *= u.mutation_value( "noise_modifier" ); if( volume > 0 ) { - if( u.is_wearing( "rm13_armor_on" ) ) { + if( u.is_wearing( itype_rm13_armor_on ) ) { volume = 2; } else if( u.has_bionic( bionic_id( "bio_ankles" ) ) ) { volume = 12; @@ -10229,7 +10240,7 @@ void game::vertical_move( int movez, bool force ) u.oxygen = 30 + 2 * u.str_cur; add_msg( _( "You dive underwater!" ) ); } else { - if( u.swim_speed() < 500 || u.shoe_type_count( "swim_fins" ) ) { + if( u.swim_speed() < 500 || u.shoe_type_count( itype_swim_fins ) ) { u.set_underwater( false ); add_msg( _( "You surface." ) ); } else { @@ -10568,7 +10579,7 @@ void game::vertical_move( int movez, bool force ) } if( m.ter( stairs ) == t_manhole_cover ) { - m.spawn_item( stairs + point( rng( -1, 1 ), rng( -1, 1 ) ), "manhole_cover" ); + m.spawn_item( stairs + point( rng( -1, 1 ), rng( -1, 1 ) ), itype_manhole_cover ); m.ter_set( stairs, t_manhole ); } @@ -10739,17 +10750,17 @@ cata::optional game::find_or_make_stairs( map &mp, const int z_after, } else { return cata::nullopt; } - } else if( u.has_amount( "grapnel", 1 ) ) { + } else if( u.has_amount( itype_grapnel, 1 ) ) { if( query_yn( _( "There is a sheer drop halfway down. Climb your grappling hook down?" ) ) ) { rope_ladder = true; - u.use_amount( "grapnel", 1 ); + u.use_amount( itype_grapnel, 1 ); } else { return cata::nullopt; } - } else if( u.has_amount( "rope_30", 1 ) ) { + } else if( u.has_amount( itype_rope_30, 1 ) ) { if( query_yn( _( "There is a sheer drop halfway down. Climb your rope down?" ) ) ) { rope_ladder = true; - u.use_amount( "rope_30", 1 ); + u.use_amount( itype_rope_30, 1 ); } else { return cata::nullopt; } diff --git a/src/game.h b/src/game.h index db6fca45f17c3..78cc450d5ef7b 100644 --- a/src/game.h +++ b/src/game.h @@ -93,8 +93,6 @@ enum action_id : int; struct special_game; -using itype_id = std::string; - class achievements_tracker; class avatar; class event_bus; diff --git a/src/gamemode_defense.h b/src/gamemode_defense.h index 20232fb614743..c390be1136249 100644 --- a/src/gamemode_defense.h +++ b/src/gamemode_defense.h @@ -14,7 +14,6 @@ #include "type_id.h" enum action_id : int; -using itype_id = std::string; enum defense_style { DEFENSE_CUSTOM = 0, diff --git a/src/gamemode_tutorial.cpp b/src/gamemode_tutorial.cpp index c1d231dc93ceb..1e15a38923087 100644 --- a/src/gamemode_tutorial.cpp +++ b/src/gamemode_tutorial.cpp @@ -34,6 +34,12 @@ #include "units.h" #include "weather.h" +static const itype_id itype_cig( "cig" ); +static const itype_id itype_codeine( "codeine" ); +static const itype_id itype_flashlight( "flashlight" ); +static const itype_id itype_grenade_act( "grenade_act" ); +static const itype_id itype_water( "water" ); + static const skill_id skill_gun( "gun" ); static const skill_id skill_melee( "melee" ); @@ -161,7 +167,7 @@ void tutorial_game::per_turn() add_message( tut_lesson::LESSON_LOOK ); if( g->light_level( g->u.posz() ) == 1 ) { - if( g->u.has_amount( "flashlight", 1 ) ) { + if( g->u.has_amount( itype_flashlight, 1 ) ) { add_message( tut_lesson::LESSON_DARK ); } else { add_message( tut_lesson::LESSON_DARK_NO_FLASH ); @@ -247,7 +253,7 @@ void tutorial_game::post_action( action_id act ) break; case ACTION_USE: - if( g->u.has_amount( "grenade_act", 1 ) ) { + if( g->u.has_amount( itype_grenade_act, 1 ) ) { add_message( tut_lesson::LESSON_ACT_GRENADE ); } for( const tripoint &dest : g->m.points_in_radius( g->u.pos(), 1 ) ) { @@ -258,11 +264,11 @@ void tutorial_game::post_action( action_id act ) break; case ACTION_EAT: - if( g->u.last_item == "codeine" ) { + if( g->u.last_item == itype_codeine ) { add_message( tut_lesson::LESSON_TOOK_PAINKILLER ); - } else if( g->u.last_item == "cig" ) { + } else if( g->u.last_item == itype_cig ) { add_message( tut_lesson::LESSON_TOOK_CIG ); - } else if( g->u.last_item == "water" ) { + } else if( g->u.last_item == itype_water ) { add_message( tut_lesson::LESSON_DRANK_WATER ); } break; diff --git a/src/handle_action.cpp b/src/handle_action.cpp index a953ba7e71d49..c514fa357923d 100644 --- a/src/handle_action.cpp +++ b/src/handle_action.cpp @@ -96,6 +96,10 @@ static const efftype_id effect_alarm_clock( "alarm_clock" ); static const efftype_id effect_laserlocked( "laserlocked" ); static const efftype_id effect_relax_gas( "relax_gas" ); +static const itype_id itype_radio_car_on( "radio_car_on" ); +static const itype_id itype_radiocontrol( "radiocontrol" ); +static const itype_id itype_shoulder_strap( "shoulder_strap" ); + static const skill_id skill_melee( "melee" ); static const quality_id qual_CUT( "CUT" ); @@ -401,7 +405,7 @@ inline static void rcdrive( const point &d ) auto rc_pairs = m.get_rc_items( tripoint( cx, cy, cz ) ); auto rc_pair = rc_pairs.begin(); for( ; rc_pair != rc_pairs.end(); ++rc_pair ) { - if( rc_pair->second->typeId() == "radio_car_on" && rc_pair->second->active ) { + if( rc_pair->second->typeId() == itype_radio_car_on && rc_pair->second->active ) { break; } } @@ -1343,7 +1347,7 @@ static void fire() actions.emplace_back( [&] { u.invoke_item( &w, "holster" ); } ); - } else if( w.is_gun() && w.gunmod_find( "shoulder_strap" ) ) { + } else if( w.is_gun() && w.gunmod_find( itype_shoulder_strap ) ) { // wield item currently worn using shoulder strap options.push_back( w.display_name() ); actions.emplace_back( [&] { u.wield( w ); } ); @@ -1761,7 +1765,8 @@ bool game::handle_action() case ACTION_MOVE_LEFT: case ACTION_MOVE_FORTH_LEFT: if( !u.get_value( "remote_controlling" ).empty() && - ( u.has_active_item( "radiocontrol" ) || u.has_active_bionic( bio_remote ) ) ) { + ( u.has_active_item( itype_radiocontrol ) || + u.has_active_bionic( bio_remote ) ) ) { rcdrive( get_delta_from_movement_action( act, iso_rotate::yes ) ); } else if( veh_ctrl ) { // vehicle control uses x for steering and y for ac/deceleration, diff --git a/src/harvest.cpp b/src/harvest.cpp index 018a8dd82e48a..f6969e6f72223 100644 --- a/src/harvest.cpp +++ b/src/harvest.cpp @@ -99,7 +99,8 @@ void harvest_list::finalize() { std::transform( entries_.begin(), entries_.end(), std::inserter( names_, names_.begin() ), []( const harvest_entry & entry ) { - return item::type_is_defined( entry.drop ) ? item::nname( entry.drop ) : ""; + return item::type_is_defined( itype_id( entry.drop ) ) ? + item::nname( itype_id( entry.drop ) ) : ""; } ); } @@ -128,8 +129,9 @@ void harvest_list::check_consistency() auto error_func = [&]( const harvest_entry & entry ) { std::string errorlist; bool item_valid = true; - if( !( item::type_is_defined( entry.drop ) || ( entry.type == "bionic_group" && - item_group::group_is_defined( entry.drop ) ) ) ) { + if( !( item::type_is_defined( itype_id( entry.drop ) ) || + ( entry.type == "bionic_group" && + item_group::group_is_defined( entry.drop ) ) ) ) { item_valid = false; errorlist += entry.drop; } @@ -203,7 +205,7 @@ std::string harvest_list::describe( int at_skill ) const } std::string ss; - ss += "" + item::nname( en.drop, max_drops ) + ""; + ss += "" + item::nname( itype_id( en.drop ), max_drops ) + ""; // If the number is unspecified, just list the type if( max_drops >= 1000 && min_drops <= 0 ) { return ss; diff --git a/src/harvest.h b/src/harvest.h index ab6e442125acf..60980e6798f51 100644 --- a/src/harvest.h +++ b/src/harvest.h @@ -13,12 +13,12 @@ #include "translations.h" #include "type_id.h" -using itype_id = std::string; class JsonObject; // Could be reused for butchery struct harvest_entry { - itype_id drop = "null"; + // drop can be either an itype_id or a group id + std::string drop = "null"; std::pair base_num = { 1.0f, 1.0f }; // This is multiplied by survival and added to the above // TODO: Make it a map: skill->scaling diff --git a/src/iexamine.cpp b/src/iexamine.cpp index dc1ae54fc5b29..27bc4153929f4 100644 --- a/src/iexamine.cpp +++ b/src/iexamine.cpp @@ -107,6 +107,40 @@ static const efftype_id effect_pkill2( "pkill2" ); static const efftype_id effect_sleep( "sleep" ); static const efftype_id effect_teleglow( "teleglow" ); +static const itype_id itype_2x4( "2x4" ); +static const itype_id itype_bot_broken_cyborg( "bot_broken_cyborg" ); +static const itype_id itype_bot_prototype_cyborg( "bot_prototype_cyborg" ); +static const itype_id itype_cash_card( "cash_card" ); +static const itype_id itype_charcoal( "charcoal" ); +static const itype_id itype_chem_carbide( "chem_carbide" ); +static const itype_id itype_corpse( "corpse" ); +static const itype_id itype_electrohack( "electrohack" ); +static const itype_id itype_hickory_root( "hickory_root" ); +static const itype_id itype_fake_milling_item( "fake_milling_item" ); +static const itype_id itype_fake_smoke_plume( "fake_smoke_plume" ); +static const itype_id itype_fertilizer( "fertilizer" ); +static const itype_id itype_fire( "fire" ); +static const itype_id itype_flour( "flour" ); +static const itype_id itype_fungal_seeds( "fungal_seeds" ); +static const itype_id itype_id_industrial( "id_industrial" ); +static const itype_id itype_id_military( "id_military" ); +static const itype_id itype_id_science( "id_science" ); +static const itype_id itype_maple_sap( "maple_sap" ); +static const itype_id itype_maple_syrup( "maple_syrup" ); +static const itype_id itype_marloss_berry( "marloss_berry" ); +static const itype_id itype_marloss_seed( "marloss_seed" ); +static const itype_id itype_mycus_fruit( "mycus_fruit" ); +static const itype_id itype_nail( "nail" ); +static const itype_id itype_petrified_eye( "petrified_eye" ); +static const itype_id itype_sheet( "sheet" ); +static const itype_id itype_stick( "stick" ); +static const itype_id itype_string_36( "string_36" ); +static const itype_id itype_tree_spile( "tree_spile" ); +static const itype_id itype_unfinished_cac2( "unfinished_cac2" ); +static const itype_id itype_unfinished_charcoal( "unfinished_charcoal" ); +static const itype_id itype_UPS( "UPS" ); +static const itype_id itype_water( "water" ); + static const trap_str_id tr_unfinished_construction( "tr_unfinished_construction" ); static const skill_id skill_computer( "computer" ); @@ -181,10 +215,6 @@ static const std::string flag_VARSIZE( "VARSIZE" ); static const std::string flag_WALL( "WALL" ); static const std::string flag_WRITE_MESSAGE( "WRITE_MESSAGE" ); -static void pick_plant( player &p, const tripoint &examp, const std::string &itemType, - ter_id new_ter, - bool seeds = false ); - /** * Nothing player can interact with here. */ @@ -405,8 +435,8 @@ class atm_menu //! Reset and repopulate the menu; with a fair bit of work this could be more efficient. void reset( const bool clear = true ) { - const int card_count = u.amount_of( "cash_card" ); - const int charge_count = card_count ? u.charges_of( "cash_card" ) : 0; + const int card_count = u.amount_of( itype_cash_card ); + const int charge_count = card_count ? u.charges_of( itype_cash_card ) : 0; if( clear ) { amenu.reset(); @@ -494,7 +524,7 @@ class atm_menu //!Deposit money from cash card into bank account. bool do_deposit_money() { - int money = u.charges_of( "cash_card" ); + int money = u.charges_of( itype_cash_card ); if( !money ) { popup( _( "You can only deposit money from charged cash cards!" ) ); @@ -510,7 +540,7 @@ class atm_menu } add_msg( m_info, "amount: %d", amount ); - u.use_charges( "cash_card", amount ); + u.use_charges( itype_cash_card, amount ); u.cash += amount; u.moves -= to_turns( 10_seconds ); finish_interaction(); @@ -522,7 +552,7 @@ class atm_menu bool do_withdraw_money() { //We may want to use visit_items here but that's fairly heavy. //For now, just check weapon if we didn't find it in the inventory. - int pos = u.inv.position_by_type( "cash_card" ); + int pos = u.inv.position_by_type( itype_cash_card ); item *dst; if( pos == INT_MIN ) { dst = &u.weapon; @@ -558,11 +588,11 @@ class atm_menu if( u.activity.id() == ACT_ATM ) { u.activity.set_to_null(); // stop for now, if required, it will be created again. dst = u.activity.targets.front().get_item(); - if( dst->is_null() || dst->typeId() != "cash_card" ) { + if( dst->is_null() || dst->typeId() != itype_cash_card ) { return false; } } else { - const int pos = u.inv.position_by_type( "cash_card" ); + const int pos = u.inv.position_by_type( itype_cash_card ); if( pos == INT_MIN ) { return false; @@ -571,7 +601,7 @@ class atm_menu } for( auto &i : u.inv_dump() ) { - if( i == dst || i->charges <= 0 || i->typeId() != "cash_card" ) { + if( i == dst || i->charges <= 0 || i->typeId() != itype_cash_card ) { continue; } if( u.moves < 0 ) { @@ -610,7 +640,7 @@ void iexamine::atm( player &p, const tripoint & ) void iexamine::vending( player &p, const tripoint &examp ) { constexpr int moves_cost = to_turns( 5_seconds ); - int money = p.charges_of( "cash_card" ); + int money = p.charges_of( itype_cash_card ); auto vend_items = g->m.i_at( examp ); if( vend_items.empty() ) { @@ -763,7 +793,7 @@ void iexamine::vending( player &p, const tripoint &examp ) } money -= iprice; - p.use_charges( "cash_card", iprice ); + p.use_charges( itype_cash_card, iprice ); p.i_add_or_drop( *cur_item ); vend_items.erase( cur_item ); @@ -793,7 +823,7 @@ void iexamine::toilet( player &p, const tripoint &examp ) auto items = g->m.i_at( examp ); auto water = items.begin(); for( ; water != items.end(); ++water ) { - if( water->typeId() == "water" ) { + if( water->typeId() == itype_water ) { break; } } @@ -886,8 +916,9 @@ void iexamine::controls_gate( player &p, const tripoint &examp ) void iexamine::cardreader( player &p, const tripoint &examp ) { bool open = false; - itype_id card_type = ( g->m.ter( examp ) == t_card_science ? "id_science" : - g->m.ter( examp ) == t_card_military ? "id_military" : "id_industrial" ); + itype_id card_type = ( g->m.ter( examp ) == t_card_science ? itype_id_science : + g->m.ter( examp ) == t_card_military ? itype_id_military : + itype_id_industrial ); if( p.has_amount( card_type, 1 ) && query_yn( _( "Swipe your ID card?" ) ) ) { p.mod_moves( -to_turns( 1_seconds ) ); for( const tripoint &tmp : g->m.points_in_radius( examp, 3 ) ) { @@ -919,7 +950,7 @@ void iexamine::cardreader( player &p, const tripoint &examp ) void iexamine::cardreader_robofac( player &p, const tripoint &examp ) { - itype_id card_type = "id_science"; + itype_id card_type = itype_id_science; if( p.has_amount( card_type, 1 ) && query_yn( _( "Swipe your ID card?" ) ) ) { p.mod_moves( -100 ); p.use_amount( card_type, 1 ); @@ -1133,7 +1164,7 @@ void iexamine::portable_structure( player &p, const tripoint &examp ) { const furn_str_id fid = g->m.furn( examp ).id(); const std::pair tent_item_type = find_tent_itype( fid ); - if( tent_item_type.first == "null" ) { + if( tent_item_type.first.is_null() ) { debugmsg( "unknown furniture %s: don't know how to transform it into an item", fid.str() ); return; } @@ -1178,12 +1209,12 @@ void iexamine::portable_structure( player &p, const tripoint &examp ) void iexamine::pit( player &p, const tripoint &examp ) { const inventory &crafting_inv = p.crafting_inventory(); - if( !crafting_inv.has_amount( "2x4", 1 ) ) { + if( !crafting_inv.has_amount( itype_2x4, 1 ) ) { none( p, examp ); return; } std::vector planks; - planks.push_back( item_comp( "2x4", 1 ) ); + planks.push_back( item_comp( itype_2x4, 1 ) ); if( query_yn( _( "Place a plank over the pit?" ) ) ) { p.consume_items( planks, 1, is_crafting_component ); @@ -1461,14 +1492,14 @@ void iexamine::pedestal_wyrm( player &p, const tripoint &examp ) void iexamine::pedestal_temple( player &p, const tripoint &examp ) { map_stack items = g->m.i_at( examp ); - if( !items.empty() && items.only_item().typeId() == "petrified_eye" ) { + if( !items.empty() && items.only_item().typeId() == itype_petrified_eye ) { add_msg( _( "The pedestal sinks into the ground…" ) ); g->m.ter_set( examp, t_dirt ); g->m.i_clear( examp ); g->timed_events.add( TIMED_EVENT_TEMPLE_OPEN, calendar::turn + 10_seconds ); - } else if( p.has_amount( "petrified_eye", 1 ) && + } else if( p.has_amount( itype_petrified_eye, 1 ) && query_yn( _( "Place your petrified eye on the pedestal?" ) ) ) { - p.use_amount( "petrified_eye", 1 ); + p.use_amount( itype_petrified_eye, 1 ); add_msg( _( "The pedestal sinks into the ground…" ) ); g->m.ter_set( examp, t_dirt ); g->timed_events.add( TIMED_EVENT_TEMPLE_OPEN, calendar::turn + 10_seconds ); @@ -1882,7 +1913,7 @@ void iexamine::flower_marloss( player &p, const tripoint &examp ) return; } g->m.furn_set( examp, f_null ); - g->m.spawn_item( p.pos(), "marloss_seed", 1, 3, calendar::turn ); + g->m.spawn_item( p.pos(), itype_marloss_seed, 1, 3, calendar::turn ); handle_harvest( p, "withered", false ); } @@ -2125,11 +2156,11 @@ void iexamine::harvest_plant( player &p, const tripoint &examp, bool from_activi return; } - const std::string &seedType = seed->typeId(); - if( seedType == "fungal_seeds" ) { + const itype_id &seedType = seed->typeId(); + if( seedType == itype_fungal_seeds ) { fungus( p, examp ); g->m.i_clear( examp ); - } else if( seedType == "marloss_seed" ) { + } else if( seedType == itype_marloss_seed ) { fungus( p, examp ); g->m.i_clear( examp ); if( p.has_trait( trait_M_DEPENDENT ) && ( p.get_kcal_percent() < 0.8f || p.get_thirst() > 300 ) ) { @@ -2225,7 +2256,7 @@ void iexamine::fertilize_plant( player &p, const tripoint &tile, const itype_id // must be on the square of the plant, therefore this hack: const auto old_furn = g->m.furn( tile ); g->m.furn_set( tile, f_null ); - g->m.spawn_item( tile, "fertilizer", 1, 1, calendar::turn ); + g->m.spawn_item( tile, itype_fertilizer, 1, 1, calendar::turn ); g->m.furn_set( tile, old_furn ); p.mod_moves( -to_moves( 10_seconds ) ); @@ -2294,7 +2325,7 @@ void iexamine::aggie_plant( player &p, const tripoint &examp ) } itype_id fertilizer = choose_fertilizer( p, pname, true /*ask player for confirmation */ ); - if( !fertilizer.empty() ) { + if( !fertilizer.is_empty() ) { fertilize_plant( p, examp, fertilizer ); } } @@ -2319,7 +2350,7 @@ void iexamine::kiln_empty( player &p, const tripoint &examp ) bool fuel_present = false; auto items = g->m.i_at( examp ); for( const item &i : items ) { - if( i.typeId() == "charcoal" ) { + if( i.typeId() == itype_charcoal ) { add_msg( _( "This kiln already contains charcoal." ) ); add_msg( _( "Remove it before firing the kiln again." ) ); return; @@ -2348,14 +2379,14 @@ void iexamine::kiln_empty( player &p, const tripoint &examp ) total_volume += i.volume(); } - auto char_type = item::find_type( "unfinished_charcoal" ); + auto char_type = item::find_type( itype_unfinished_charcoal ); int char_charges = char_type->charges_per_volume( ( 100 - loss ) * total_volume / 100 ); if( char_charges < 1 ) { add_msg( _( "The batch in this kiln is too small to yield any charcoal." ) ); return; } - if( !p.has_charges( "fire", 1 ) ) { + if( !p.has_charges( itype_fire, 1 ) ) { add_msg( _( "This kiln is ready to be fired, but you have no fire source." ) ); return; } else { @@ -2366,7 +2397,7 @@ void iexamine::kiln_empty( player &p, const tripoint &examp ) } } - p.use_charges( "fire", 1 ); + p.use_charges( itype_fire, 1 ); g->m.i_clear( examp ); g->m.furn_set( examp, next_kiln_type ); item result( "unfinished_charcoal", calendar::turn ); @@ -2395,7 +2426,7 @@ void iexamine::kiln_full( player &, const tripoint &examp ) g->m.furn_set( examp, next_kiln_type ); return; } - auto char_type = item::find_type( "charcoal" ); + auto char_type = item::find_type( itype_charcoal ); add_msg( _( "There's a charcoal kiln there." ) ); const time_duration firing_time = 6_hours; // 5 days in real life const time_duration time_left = firing_time - items.only_item().age(); @@ -2417,7 +2448,7 @@ void iexamine::kiln_full( player &, const tripoint &examp ) units::volume total_volume = 0_ml; // Burn stuff that should get charred, leave out the rest for( auto item_it = items.begin(); item_it != items.end(); ) { - if( item_it->typeId() == "unfinished_charcoal" || item_it->typeId() == "charcoal" ) { + if( item_it->typeId() == itype_unfinished_charcoal || item_it->typeId() == itype_charcoal ) { total_volume += item_it->volume(); item_it = items.erase( item_it ); } else { @@ -2448,7 +2479,7 @@ void iexamine::arcfurnace_empty( player &p, const tripoint &examp ) bool fuel_present = false; auto items = g->m.i_at( examp ); for( const item &i : items ) { - if( i.typeId() == "chem_carbide" ) { + if( i.typeId() == itype_chem_carbide ) { add_msg( _( "This furnace already contains calcium carbide." ) ); add_msg( _( "Remove it before activating the arc furnace again." ) ); return; @@ -2477,14 +2508,14 @@ void iexamine::arcfurnace_empty( player &p, const tripoint &examp ) total_volume += i.volume(); } - auto char_type = item::find_type( "unfinished_cac2" ); + auto char_type = item::find_type( itype_unfinished_cac2 ); int char_charges = char_type->charges_per_volume( ( 100 - loss ) * total_volume / 100 ); if( char_charges < 1 ) { add_msg( _( "The batch in this furance is too small to yield usable calcium carbide." ) ); return; } //arc furnaces require a huge amount of current, so 1 full storage battery would work as a stand in - if( !p.has_charges( "UPS", 1250 ) ) { + if( !p.has_charges( itype_UPS, 1250 ) ) { add_msg( _( "This furnace is ready to be turned on, but you lack a UPS with sufficient power." ) ); return; } else { @@ -2495,7 +2526,7 @@ void iexamine::arcfurnace_empty( player &p, const tripoint &examp ) } } - p.use_charges( "UPS", 1250 ); + p.use_charges( itype_UPS, 1250 ); g->m.i_clear( examp ); g->m.furn_set( examp, next_arcfurnace_type ); item result( "unfinished_cac2", calendar::turn ); @@ -2522,7 +2553,7 @@ void iexamine::arcfurnace_full( player &, const tripoint &examp ) g->m.furn_set( examp, next_arcfurnace_type ); return; } - auto char_type = item::find_type( "chem_carbide" ); + auto char_type = item::find_type( itype_chem_carbide ); add_msg( _( "There's an arc furnace there." ) ); const time_duration firing_time = 2_hours; // Arc furnaces work really fast in reality const time_duration time_left = firing_time - items.only_item().age(); @@ -2544,7 +2575,7 @@ void iexamine::arcfurnace_full( player &, const tripoint &examp ) units::volume total_volume = 0_ml; // Burn stuff that should get charred, leave out the rest for( auto item_it = items.begin(); item_it != items.end(); ) { - if( item_it->typeId() == "unfinished_cac2" || item_it->typeId() == "chem_carbide" ) { + if( item_it->typeId() == itype_unfinished_cac2 || item_it->typeId() == itype_chem_carbide ) { total_volume += item_it->volume(); item_it = items.erase( item_it ); } else { @@ -2679,7 +2710,7 @@ void iexamine::autoclave_full( player &, const tripoint &examp ) void iexamine::fireplace( player &p, const tripoint &examp ) { const bool already_on_fire = g->m.has_nearby_fire( examp, 0 ); - const bool furn_is_deployed = !g->m.furn( examp ).obj().deployed_item.empty(); + const bool furn_is_deployed = !g->m.furn( examp ).obj().deployed_item.is_empty(); std::multimap firestarters; for( item *it : p.items_with( []( const item & it ) { @@ -3210,8 +3241,8 @@ bool iexamine::pour_into_keg( const tripoint &pos, item &liquid ) return true; } -void pick_plant( player &p, const tripoint &examp, - const std::string &itemType, ter_id new_ter, bool seeds ) +static void pick_plant( player &p, const tripoint &examp, + const itype_id &itemType, ter_id new_ter, bool seeds = false ) { bool auto_forage = get_option( "AUTO_FEATURES" ) && get_option( "AUTO_FORAGING" ) != "off"; @@ -3232,7 +3263,8 @@ void pick_plant( player &p, const tripoint &examp, g->m.spawn_item( p.pos(), itemType, plantCount, 0, calendar::turn ); if( seeds ) { - g->m.spawn_item( p.pos(), "seed_" + itemType, 1, + // FIXME: shouldn't derive seed type by string manipulation + g->m.spawn_item( p.pos(), itype_id( "seed_" + itemType.str() ), 1, rng( plantCount / 4, plantCount / 2 ), calendar::turn ); } @@ -3254,7 +3286,7 @@ void iexamine::tree_hickory( player &p, const tripoint &examp ) } ///\EFFECT_SURVIVAL increases hickory root number per tree - g->m.spawn_item( p.pos(), "hickory_root", rng( 1, 3 + p.get_skill_level( skill_survival ) ), 0, + g->m.spawn_item( p.pos(), itype_hickory_root, rng( 1, 3 + p.get_skill_level( skill_survival ) ), 0, calendar::turn ); g->m.ter_set( examp, t_tree_hickory_dead ); ///\EFFECT_SURVIVAL speeds up hickory root digging @@ -3284,14 +3316,14 @@ void iexamine::tree_maple( player &p, const tripoint &examp ) const inventory &crafting_inv = p.crafting_inventory(); - if( !crafting_inv.has_amount( "tree_spile", 1 ) ) { + if( !crafting_inv.has_amount( itype_tree_spile, 1 ) ) { add_msg( m_info, _( "You need a %s to tap this maple tree." ), - item::nname( "tree_spile" ) ); + item::nname( itype_tree_spile ) ); return; } std::vector comps; - comps.push_back( item_comp( "tree_spile", 1 ) ); + comps.push_back( item_comp( itype_tree_spile, 1 ) ); p.consume_items( comps, 1, is_crafting_component ); p.mod_moves( -to_moves( 20_seconds ) ); @@ -3315,7 +3347,7 @@ void iexamine::tree_maple_tapped( player &p, const tripoint &examp ) item *container = nullptr; int charges = 0; - const std::string maple_sap_name = item::nname( "maple_sap" ); + const std::string maple_sap_name = item::nname( itype_maple_sap ); map_stack items = g->m.i_at( examp ); if( !items.empty() ) { @@ -3324,7 +3356,7 @@ void iexamine::tree_maple_tapped( player &p, const tripoint &examp ) container = ⁢ it.visit_items( [&charges, &has_sap]( const item * it ) { - if( it->typeId() == "maple_syrup" ) { + if( it->typeId() == itype_maple_syrup ) { has_sap = true; charges = it->charges; return VisitResponse::ABORT; @@ -3407,20 +3439,20 @@ void iexamine::tree_maple_tapped( player &p, const tripoint &examp ) void iexamine::shrub_marloss( player &p, const tripoint &examp ) { if( p.has_trait( trait_THRESH_MYCUS ) ) { - pick_plant( p, examp, "mycus_fruit", t_shrub_fungal ); + pick_plant( p, examp, itype_mycus_fruit, t_shrub_fungal ); } else if( p.has_trait( trait_THRESH_MARLOSS ) ) { - g->m.spawn_item( p.pos(), "mycus_fruit", 1, 0, calendar::turn ); + g->m.spawn_item( p.pos(), itype_mycus_fruit, 1, 0, calendar::turn ); g->m.ter_set( examp, t_fungus ); add_msg( m_info, _( "The shrub offers up a fruit, then crumbles into a fungal bed." ) ); } else { - pick_plant( p, examp, "marloss_berry", t_shrub_fungal ); + pick_plant( p, examp, itype_marloss_berry, t_shrub_fungal ); } } void iexamine::tree_marloss( player &p, const tripoint &examp ) { if( p.has_trait( trait_THRESH_MYCUS ) ) { - pick_plant( p, examp, "mycus_fruit", t_tree_fungal ); + pick_plant( p, examp, itype_mycus_fruit, t_tree_fungal ); if( p.has_trait( trait_M_DEPENDENT ) && one_in( 3 ) ) { // Folks have a better shot at keeping fed. add_msg( m_info, @@ -3429,11 +3461,11 @@ void iexamine::tree_marloss( player &p, const tripoint &examp ) g->m.ter_set( examp, t_marloss_tree ); } } else if( p.has_trait( trait_THRESH_MARLOSS ) ) { - g->m.spawn_item( p.pos(), "mycus_fruit", 1, 0, calendar::turn ); + g->m.spawn_item( p.pos(), itype_mycus_fruit, 1, 0, calendar::turn ); g->m.ter_set( examp, t_tree_fungal ); add_msg( m_info, _( "The tree offers up a fruit, then shrivels into a fungal tree." ) ); } else { - pick_plant( p, examp, "marloss_berry", t_tree_fungal ); + pick_plant( p, examp, itype_marloss_berry, t_tree_fungal ); } } @@ -3638,7 +3670,7 @@ void iexamine::clean_water_source( player &, const tripoint &examp ) const itype *furn_t::crafting_pseudo_item_type() const { - if( crafting_pseudo_item.empty() ) { + if( crafting_pseudo_item.is_empty() ) { return nullptr; } return item::find_type( crafting_pseudo_item ); @@ -3772,10 +3804,10 @@ void iexamine::curtains( player &p, const tripoint &examp ) g->m.ter_set( examp, t_window_bars ); } - g->m.spawn_item( p.pos(), "nail", 1, 4, calendar::turn ); - g->m.spawn_item( p.pos(), "sheet", 2, 0, calendar::turn ); - g->m.spawn_item( p.pos(), "stick", 1, 0, calendar::turn ); - g->m.spawn_item( p.pos(), "string_36", 1, 0, calendar::turn ); + g->m.spawn_item( p.pos(), itype_nail, 1, 4, calendar::turn ); + g->m.spawn_item( p.pos(), itype_sheet, 2, 0, calendar::turn ); + g->m.spawn_item( p.pos(), itype_stick, 1, 0, calendar::turn ); + g->m.spawn_item( p.pos(), itype_string_36, 1, 0, calendar::turn ); p.moves -= to_moves( 10_seconds ); p.add_msg_if_player( _( "You tear the curtains and curtain rod off the windowframe." ) ); } else { @@ -4076,8 +4108,9 @@ void iexamine::pay_gas( player &p, const tripoint &examp ) int pricePerUnit = getGasPricePerLiter( discount ); - bool can_hack = ( !p.has_trait( trait_ILLITERATE ) && ( ( p.has_charges( "electrohack", 25 ) ) || - ( p.has_bionic( bio_fingerhack ) && p.get_power_level() > 24_kJ ) ) ); + bool can_hack = ( !p.has_trait( trait_ILLITERATE ) && + ( ( p.has_charges( itype_electrohack, 25 ) ) || + ( p.has_bionic( bio_fingerhack ) && p.get_power_level() > 24_kJ ) ) ); uilist amenu; amenu.selected = 1; @@ -4128,7 +4161,7 @@ void iexamine::pay_gas( player &p, const tripoint &examp ) } if( buy_gas == choice ) { - int money = p.charges_of( "cash_card" ); + int money = p.charges_of( itype_cash_card ); if( money < pricePerUnit ) { popup( str_to_illiterate_str( @@ -4164,7 +4197,7 @@ void iexamine::pay_gas( player &p, const tripoint &examp ) int cost = liters * pricePerUnit; money -= cost; - p.use_charges( "cash_card", cost ); + p.use_charges( itype_cash_card, cost ); add_msg( m_info, _( "Your cash cards now hold %s." ), format_money( money ) ); p.moves -= to_moves( 5_seconds ); @@ -4193,7 +4226,8 @@ void iexamine::pay_gas( player &p, const tripoint &examp ) sounds::sound( p.pos(), 6, sounds::sound_t::activity, _( "Glug Glug Glug" ), true, "tool", "gaspump" ); cashcard->charges += amount * pricePerUnit / 1000.0f; - add_msg( m_info, _( "Your cash cards now hold %s." ), format_money( p.charges_of( "cash_card" ) ) ); + add_msg( m_info, _( "Your cash cards now hold %s." ), + format_money( p.charges_of( itype_cash_card ) ) ); p.moves -= to_moves( 5_seconds ); return; } else { @@ -4345,10 +4379,10 @@ static Character &operator_present( Character &p, const tripoint &autodoc_loc, static item &cyborg_on_couch( const tripoint &couch_pos, item &null_cyborg ) { for( item &it : g->m.i_at( couch_pos ) ) { - if( it.typeId() == "bot_broken_cyborg" || it.typeId() == "bot_prototype_cyborg" ) { + if( it.typeId() == itype_bot_broken_cyborg || it.typeId() == itype_bot_prototype_cyborg ) { return it; } - if( it.typeId() == "corpse" ) { + if( it.typeId() == itype_corpse ) { if( it.get_mtype()->id == mon_broken_cyborg || it.get_mtype()->id == mon_prototype_cyborg ) { return it; } @@ -4435,10 +4469,11 @@ void iexamine::autodoc( player &p, const tripoint &examp ) } if( &patient == &null_player ) { if( &cyborg != &null_cyborg ) { - if( cyborg.typeId() == "corpse" && !cyborg.active ) { + if( cyborg.typeId() == itype_corpse && !cyborg.active ) { popup( _( "Patient is dead. Please remove corpse to proceed. Exiting." ) ); return; - } else if( cyborg.typeId() == "bot_broken_cyborg" || cyborg.typeId() == "corpse" ) { + } else if( cyborg.typeId() == itype_id( "bot_broken_cyborg" ) || + cyborg.typeId() == itype_id( "corpse" ) ) { popup( _( "ERROR Bionic Level Assessment: FULL CYBORG. Autodoc Mk. XI can't operate. Please move patient to appropriate facility. Exiting." ) ); return; } @@ -4572,7 +4607,7 @@ void iexamine::autodoc( player &p, const tripoint &examp ) for( const bionic &bio : installed_bionics ) { if( bio.id != bio_power_storage || bio.id != bio_power_storage_mkII ) { - if( item::type_is_defined( bio.id.str() ) ) {// put cbm items in your inventory + if( item::type_is_defined( bio.info().itype() ) ) {// put cbm items in your inventory item bionic_to_uninstall( bio.id.str(), calendar::turn ); bionic_to_uninstall.set_flag( flag_IN_CBM ); bionic_to_uninstall.set_flag( flag_NO_STERILE ); @@ -4704,7 +4739,7 @@ static void mill_activate( player &p, const tripoint &examp ) units::volume food_volume = 0_ml; for( item &it : items ) { - if( it.typeId() == "flour" ) { + if( it.typeId() == itype_flour ) { add_msg( _( "This mill already contains flour." ) ); add_msg( _( "Remove it before starting the mill again." ) ); return; @@ -4783,11 +4818,11 @@ static void smoker_activate( player &p, const tripoint &examp ) food_volume += it.volume(); continue; } - if( it.typeId() == "charcoal" ) { + if( it.typeId() == itype_charcoal ) { charcoal_present = true; charcoal = ⁢ } - if( it.typeId() != "charcoal" && !it.has_flag( flag_SMOKABLE ) ) { + if( it.typeId() != itype_charcoal && !it.has_flag( flag_SMOKABLE ) ) { add_msg( m_bad, _( "This rack contains %s, which can't be smoked!" ), it.tname( 1, false ) ); add_msg( _( "You remove %s from the rack." ), it.tname() ); @@ -4829,14 +4864,14 @@ static void smoker_activate( player &p, const tripoint &examp ) return; } - if( !p.has_charges( "fire", 1 ) ) { + if( !p.has_charges( itype_fire, 1 ) ) { add_msg( _( "This smoking rack is ready to be fired, but you have no fire source." ) ); return; } else if( !query_yn( _( "Fire the smoking rack?" ) ) ) { return; } - p.use_charges( "fire", 1 ); + p.use_charges( itype_fire, 1 ); for( auto &it : g->m.i_at( examp ) ) { if( it.has_flag( flag_SMOKABLE ) ) { it.process_temperature_rot( 1, examp, nullptr ); @@ -4912,7 +4947,7 @@ static void smoker_finalize( player &, const tripoint &examp, const time_point & for( item &it : items ) { if( it.has_flag( flag_SMOKABLE ) && it.get_comestible() ) { - if( it.get_comestible()->smoking_result.empty() ) { + if( it.get_comestible()->smoking_result.is_empty() ) { it.unset_flag( flag_PROCESSING ); } else { it.calc_rot_while_processing( 6_hours ); @@ -4928,7 +4963,7 @@ static void smoker_finalize( player &, const tripoint &examp, const time_point & result.inherit_flags( it, rec ); if( !result.has_flag( flag_NUTRIENT_OVERRIDE ) ) { // If the item has "cooks_like" it will be replaced by that item as a component. - if( !it.get_comestible()->cooks_like.empty() ) { + if( !it.get_comestible()->cooks_like.is_empty() ) { // Set charges to 1 for stacking purposes. it = item( it.get_comestible()->cooks_like, it.birthday(), 1 ); } @@ -5197,7 +5232,7 @@ void iexamine::quern_examine( player &p, const tripoint &examp ) return; } - if( items_here.size() == 1 && items_here.begin()->typeId() == "fake_milling_item" ) { + if( items_here.size() == 1 && items_here.begin()->typeId() == itype_fake_milling_item ) { debugmsg( "f_mill_active was empty, and had fake_milling_item!" ); if( g->m.furn( examp ) == furn_str_id( "f_water_mill_active" ) ) { g->m.furn_set( examp, f_water_mill ); @@ -5219,7 +5254,7 @@ void iexamine::quern_examine( player &p, const tripoint &examp ) f_check = true; f_volume += it.volume(); } - if( active && it.typeId() == "fake_milling_item" ) { + if( active && it.typeId() == itype_fake_milling_item ) { time_left = time_duration::from_turns( it.item_counter ); hours_left = to_hours( time_left ); minutes_left = to_minutes( time_left ) + 1; @@ -5284,7 +5319,7 @@ void iexamine::quern_examine( player &p, const tripoint &examp ) pop += _( "…that it is empty." ); } else { for( const item &it : items_here ) { - if( it.typeId() == "fake_milling_item" ) { + if( it.typeId() == itype_fake_milling_item ) { pop += "\n" + colorize( _( "You see some grains that are not yet milled to fine flour." ), c_red ) + "\n"; continue; @@ -5362,12 +5397,12 @@ void iexamine::smoker_options( player &p, const tripoint &examp ) g->m.furn_set( examp, f_smoking_rack ); return; } - if( portable && items_here.size() == 1 && items_here.begin()->typeId() == "fake_smoke_plume" ) { + if( portable && items_here.size() == 1 && items_here.begin()->typeId() == itype_fake_smoke_plume ) { debugmsg( "f_metal_smoking_rack_active was empty, and had fake_smoke_plume!" ); g->m.furn_set( examp, f_metal_smoking_rack ); items_here.erase( items_here.begin() ); return; - } else if( items_here.size() == 1 && items_here.begin()->typeId() == "fake_smoke_plume" ) { + } else if( items_here.size() == 1 && items_here.begin()->typeId() == itype_fake_smoke_plume ) { debugmsg( "f_smoking_rack_active was empty, and had fake_smoke_plume!" ); g->m.furn_set( examp, f_smoking_rack ); items_here.erase( items_here.begin() ); @@ -5386,7 +5421,7 @@ void iexamine::smoker_options( player &p, const tripoint &examp ) f_check = true; f_volume += it.volume(); } - if( active && it.typeId() == "fake_smoke_plume" ) { + if( active && it.typeId() == itype_fake_smoke_plume ) { time_left = time_duration::from_turns( it.item_counter ); hours_left = to_hours( time_left ); minutes_left = to_minutes( time_left ) + 1; @@ -5398,8 +5433,8 @@ void iexamine::smoker_options( player &p, const tripoint &examp ) const bool full_portable = f_volume >= sm_rack::MAX_FOOD_VOLUME_PORTABLE; const auto remaining_capacity = sm_rack::MAX_FOOD_VOLUME - f_volume; const auto remaining_capacity_portable = sm_rack::MAX_FOOD_VOLUME_PORTABLE - f_volume; - const auto has_coal_in_inventory = p.charges_of( "charcoal" ) > 0; - const auto coal_charges = count_charges_in_list( item::find_type( "charcoal" ), items_here ); + const auto has_coal_in_inventory = p.charges_of( itype_charcoal ) > 0; + const auto coal_charges = count_charges_in_list( item::find_type( itype_charcoal ), items_here ); const auto need_charges = get_charcoal_charges( f_volume ); const bool has_coal = coal_charges > 0; const bool has_enough_coal = coal_charges >= need_charges; @@ -5489,7 +5524,7 @@ void iexamine::smoker_options( player &p, const tripoint &examp ) pop += _( "…that it is empty." ); } else { for( const item &it : items_here ) { - if( it.typeId() == "fake_smoke_plume" ) { + if( it.typeId() == itype_fake_smoke_plume ) { pop += "\n" + colorize( _( "You see some smoldering embers there." ), c_red ) + "\n"; continue; } @@ -5526,7 +5561,7 @@ void iexamine::smoker_options( player &p, const tripoint &examp ) case 5: { //remove charcoal for( map_stack::iterator it = items_here.begin(); it != items_here.end(); ) { - if( ( rem_f_opt && it->is_food() ) || ( !rem_f_opt && ( it->typeId() == "charcoal" ) ) ) { + if( ( rem_f_opt && it->is_food() ) || ( !rem_f_opt && ( it->typeId() == itype_charcoal ) ) ) { // get handling cost before the item reference is invalidated const int handling_cost = -p.item_handling_cost( *it ); diff --git a/src/inventory.cpp b/src/inventory.cpp index 7389ebe795c1a..415484b3a6b2f 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -35,6 +35,15 @@ #include "point.h" #include "inventory_ui.h" // auto inventory blocking +static const itype_id itype_aspirin( "aspirin" ); +static const itype_id itype_battery( "battery" ); +static const itype_id itype_codeine( "codeine" ); +static const itype_id itype_heroin( "heroin" ); +static const itype_id itype_salt_water( "salt_water" ); +static const itype_id itype_tramadol( "tramadol" ); +static const itype_id itype_oxycodone( "oxycodone" ); +static const itype_id itype_water( "water" ); + static const std::string flag_LEAK_ALWAYS( "LEAK_ALWAYS" ); static const std::string flag_LEAK_DAM( "LEAK_DAM" ); static const std::string flag_WATERPROOF( "WATERPROOF" ); @@ -63,9 +72,9 @@ invlet_favorites::invlet_favorites( const std::unordered_map pts, const Characte auto toilet = m.i_at( p ); auto water = toilet.end(); for( auto candidate = toilet.begin(); candidate != toilet.end(); ++candidate ) { - if( candidate->typeId() == "water" ) { + if( candidate->typeId() == itype_water ) { water = candidate; break; } @@ -537,7 +546,7 @@ void inventory::form_from_map( map &m, std::vector pts, const Characte } if( kpart ) { - int veh_battery = veh->fuel_left( "battery", true ); + int veh_battery = veh->fuel_left( itype_battery, true ); item hotplate( "hotplate", 0 ); hotplate.ammo_set( hotplate.ammo_default(), veh_battery ); hotplate.item_tags.insert( "PSEUDO" ); @@ -551,7 +560,7 @@ void inventory::form_from_map( map &m, std::vector pts, const Characte add_item( pan ); } if( weldpart ) { - int veh_battery = veh->fuel_left( "battery", true ); + int veh_battery = veh->fuel_left( itype_battery, true ); item welder( "welder", 0 ); welder.ammo_set( welder.ammo_default(), veh_battery ); welder.item_tags.insert( "PSEUDO" ); @@ -563,7 +572,7 @@ void inventory::form_from_map( map &m, std::vector pts, const Characte add_item( soldering_iron ); } if( craftpart ) { - int veh_battery = veh->fuel_left( "battery", true ); + int veh_battery = veh->fuel_left( itype_battery, true ); item vac_sealer( "vac_sealer", 0 ); vac_sealer.ammo_set( vac_sealer.ammo_default(), veh_battery ); vac_sealer.item_tags.insert( "PSEUDO" ); @@ -585,21 +594,21 @@ void inventory::form_from_map( map &m, std::vector pts, const Characte add_item( press ); } if( forgepart ) { - int veh_battery = veh->fuel_left( "battery", true ); + int veh_battery = veh->fuel_left( itype_battery, true ); item forge( "forge", 0 ); forge.ammo_set( forge.ammo_default(), veh_battery ); forge.item_tags.insert( "PSEUDO" ); add_item( forge ); } if( kilnpart ) { - int veh_battery = veh->fuel_left( "battery", true ); + int veh_battery = veh->fuel_left( itype_battery, true ); item kiln( "kiln", 0 ); kiln.ammo_set( kiln.ammo_default(), veh_battery ); kiln.item_tags.insert( "PSEUDO" ); add_item( kiln ); } if( chempart ) { - int veh_battery = veh->fuel_left( "battery", true ); + int veh_battery = veh->fuel_left( itype_battery, true ); item chemistry_set( "chemistry_set", 0 ); chemistry_set.ammo_set( chemistry_set.ammo_default(), veh_battery ); chemistry_set.item_tags.insert( "PSEUDO" ); @@ -848,9 +857,9 @@ bool inventory::has_enough_painkiller( int pain ) const { for( const auto &elem : items ) { const item &it = elem.front(); - if( ( pain <= 35 && it.typeId() == "aspirin" ) || - ( pain >= 50 && it.typeId() == "oxycodone" ) || - it.typeId() == "tramadol" || it.typeId() == "codeine" ) { + if( ( pain <= 35 && it.typeId() == itype_aspirin ) || + ( pain >= 50 && it.typeId() == itype_oxycodone ) || + it.typeId() == itype_tramadol || it.typeId() == itype_codeine ) { return true; } } @@ -864,15 +873,15 @@ item *inventory::most_appropriate_painkiller( int pain ) for( auto &elem : items ) { int diff = 9999; itype_id type = elem.front().typeId(); - if( type == "aspirin" ) { + if( type == itype_aspirin ) { diff = std::abs( pain - 15 ); - } else if( type == "codeine" ) { + } else if( type == itype_codeine ) { diff = std::abs( pain - 30 ); - } else if( type == "oxycodone" ) { + } else if( type == itype_oxycodone ) { diff = std::abs( pain - 60 ); - } else if( type == "heroin" ) { + } else if( type == itype_heroin ) { diff = std::abs( pain - 100 ); - } else if( type == "tramadol" ) { + } else if( type == itype_tramadol ) { diff = std::abs( pain - 40 ) / 2; // Bonus since it's long-acting } @@ -895,11 +904,15 @@ void inventory::rust_iron_items() //Passivation layer prevents further rusting one_in( 500 ) && //Scale with volume, bigger = slower (see #24204) - one_in( static_cast( 14 * std::cbrt( 0.5 * std::max( 0.05, - static_cast( elem_stack_iter.base_volume().value() ) / 250 ) ) ) ) && + one_in( + static_cast( + 14 * std::cbrt( + 0.5 * std::max( + 0.05, static_cast( + elem_stack_iter.base_volume().value() ) / 250 ) ) ) ) && // ^season length ^14/5*0.75/pi (from volume of sphere) - g->m.water_from( g->u.pos() ).typeId() == - "salt_water" ) { //Freshwater without oxygen rusts slower than air + //Freshwater without oxygen rusts slower than air + g->m.water_from( g->u.pos() ).typeId() == itype_salt_water ) { elem_stack_iter.inc_damage( DT_ACID ); // rusting never completely destroys an item add_msg( m_bad, _( "Your %s is damaged by rust." ), elem_stack_iter.tname() ); } diff --git a/src/inventory.h b/src/inventory.h index a7aed98076f42..c45334daa7116 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -234,7 +234,7 @@ class inventory : public visitable private: invlet_favorites invlet_cache; - char find_usable_cached_invlet( const std::string &item_type ); + char find_usable_cached_invlet( const itype_id &item_type ); invstack items; diff --git a/src/item.cpp b/src/item.cpp index 4882662e30f49..563d216b4962d 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -112,6 +112,24 @@ static const fault_id fault_gun_blackpowder( "fault_gun_blackpowder" ); static const gun_mode_id gun_mode_REACH( "REACH" ); +static const itype_id itype_adv_UPS_off( "adv_UPS_off" ); +static const itype_id itype_barrel_small( "barrel_small" ); +static const itype_id itype_blood( "blood" ); +static const itype_id itype_brass_catcher( "brass_catcher" ); +static const itype_id itype_bullet_crossbow( "bullet_crossbow" ); +static const itype_id itype_cig_butt( "cig_butt" ); +static const itype_id itype_cig_lit( "cig_lit" ); +static const itype_id itype_cigar_butt( "cigar_butt" ); +static const itype_id itype_cigar_lit( "cigar_lit" ); +static const itype_id itype_hand_crossbow( "hand_crossbow" ); +static const itype_id itype_joint_roach( "joint_roach" ); +static const itype_id itype_plut_cell( "plut_cell" ); +static const itype_id itype_rad_badge( "rad_badge" ); +static const itype_id itype_tuned_mechanism( "tuned_mechanism" ); +static const itype_id itype_UPS( "UPS" ); +static const itype_id itype_UPS_off( "UPS_off" ); +static const itype_id itype_waterproof_gunmod( "waterproof_gunmod" ); + static const skill_id skill_cooking( "cooking" ); static const skill_id skill_melee( "melee" ); static const skill_id skill_survival( "survival" ); @@ -357,16 +375,16 @@ item::item( const itype *type, time_point turn, int qty ) : type( type ), bday( if( has_flag( flag_NANOFAB_TEMPLATE ) ) { itype_id nanofab_recipe = item_group::item_from( "nanofab_recipes" ).typeId(); - set_var( "NANOFAB_ITEM_ID", nanofab_recipe ); + set_var( "NANOFAB_ITEM_ID", nanofab_recipe.str() ); } if( type->gun ) { - for( const std::string &mod : type->gun->built_in_mods ) { + for( const itype_id &mod : type->gun->built_in_mods ) { item it( mod, turn, qty ); it.item_tags.insert( "IRREMOVABLE" ); put_in( it, item_pocket::pocket_type::MOD ); } - for( const std::string &mod : type->gun->default_mods ) { + for( const itype_id &mod : type->gun->default_mods ) { put_in( item( mod, turn, qty ), item_pocket::pocket_type::MOD ); } @@ -567,7 +585,7 @@ item &item::ammo_set( const itype_id &ammo, int qty ) qty = ammo_capacity(); // else try to add a magazine using default ammo count property if set - } else if( magazine_default() != "null" ) { + } else if( !magazine_default().is_null() ) { item mag( magazine_default() ); if( mag.type->magazine->count > 0 ) { qty = mag.type->magazine->count; @@ -583,7 +601,7 @@ item &item::ammo_set( const itype_id &ammo, int qty ) } // handle reloadable tools and guns with no specific ammo type as special case - if( ( ( ammo == "null" || ammo == "NULL" ) && ammo_types().empty() ) || is_money() ) { + if( ( ( ammo.is_null() || ammo.is_null() ) && ammo_types().empty() ) || is_money() ) { if( magazine_integral() ) { if( is_tool() ) { curammo = nullptr; @@ -631,7 +649,7 @@ item &item::ammo_set( const itype_id &ammo, int qty ) auto iter = type->magazines.find( atype->ammo->type ); if( iter == type->magazines.end() ) { debugmsg( "%s doesn't have a magazine for %s", - tname(), ammo ); + tname(), ammo.str() ); return *this; } std::vector opts( iter->second.begin(), iter->second.end() ); @@ -639,7 +657,7 @@ item &item::ammo_set( const itype_id &ammo, int qty ) return find_type( lhs )->magazine->capacity < find_type( rhs )->magazine->capacity; } ); mag = find_type( opts.back() ); - for( const std::string &e : opts ) { + for( const itype_id &e : opts ) { if( find_type( e )->magazine->capacity >= qty ) { mag = find_type( e ); break; @@ -712,9 +730,8 @@ item item::split( int qty ) bool item::is_null() const { - static const std::string s_null( "null" ); // used a lot, no need to repeat // Actually, type should never by null at all. - return ( type == nullptr || type == nullitem() || typeId() == s_null ); + return ( type == nullptr || type == nullitem() || typeId().is_null() ); } bool item::is_unarmed_weapon() const @@ -826,7 +843,7 @@ item item::in_its_container() const item item::in_container( const itype_id &cont ) const { - if( cont != "null" ) { + if( !cont.is_null() ) { item ret( cont, birthday() ); if( ret.has_pockets() ) { if( count_by_charges() ) { @@ -1971,7 +1988,8 @@ void item::gun_info( const item *mod, std::vector &info, const iteminf tmp = *mod; tmp.ammo_set( mod->magazine_current() ? tmp.common_ammo_default() : tmp.ammo_default() ); loaded_mod = &tmp; - if( loaded_mod->typeId() == "none" || loaded_mod == nullptr || + // TODO: Should this be .is_null(), rather than comparing to "none"? + if( loaded_mod->typeId().str() == "none" || loaded_mod == nullptr || loaded_mod->ammo_data() == nullptr ) { debugmsg( "loaded a nun or ammo_data() is nullptr" ); return; @@ -2208,7 +2226,7 @@ void item::gun_info( const item *mod, std::vector &info, const iteminf if( !magazine_integral() && parts->test( iteminfo_parts::GUN_ALLOWED_MAGAZINES ) ) { insert_separation_line( info ); - const std::set compat = magazine_compatible(); + const std::set compat = magazine_compatible(); info.emplace_back( "DESCRIPTION", _( "Compatible magazines: " ) + enumerate_as_string( compat.begin(), compat.end(), []( const itype_id & id ) { return item::nname( id ); @@ -2339,9 +2357,7 @@ void item::gunmod_info( std::vector &info, const iteminfo_query *parts if( parts->test( iteminfo_parts::GUNMOD_USEDON ) ) { std::string used_on_str = _( "Used on: " ) + enumerate_as_string( mod.usable.begin(), mod.usable.end(), []( const gun_type_type & used_on ) { - std::string id_string = item_controller->has_template( used_on.name() ) ? nname( used_on.name(), - 1 ) : used_on.name(); - return string_format( "%s", id_string ); + return string_format( "%s", used_on.name() ); } ); info.push_back( iteminfo( "GUNMOD", used_on_str ) ); } @@ -2760,7 +2776,7 @@ void item::armor_fit_info( std::vector &info, const iteminfo_query *pa } } } - if( typeId() == "rad_badge" && parts->test( iteminfo_parts::DESCRIPTION_IRRADIATION ) ) { + if( typeId() == itype_rad_badge && parts->test( iteminfo_parts::DESCRIPTION_IRRADIATION ) ) { info.push_back( iteminfo( "DESCRIPTION", string_format( _( "* The film strip on the badge is %s." ), rad_badge_color( irradiation ) ) ) ); @@ -2950,7 +2966,7 @@ void item::tool_info( std::vector &info, const iteminfo_query *parts, } if( parts->test( iteminfo_parts::TOOL_MAGAZINE_COMPATIBLE ) ) { - const std::set compat = magazine_compatible(); + const std::set compat = magazine_compatible(); info.emplace_back( "TOOL", _( "Compatible magazines: " ), enumerate_as_string( compat.begin(), compat.end(), []( const itype_id & id ) { return item::nname( id ); @@ -3000,7 +3016,7 @@ void item::repair_info( std::vector &info, const iteminfo_query *parts return; } insert_separation_line( info ); - const std::set &rep = repaired_with(); + const std::set &rep = repaired_with(); if( !rep.empty() ) { info.emplace_back( "DESCRIPTION", string_format( _( "Repair using %s." ), enumerate_as_string( rep.begin(), rep.end(), []( const itype_id & e ) { @@ -3592,7 +3608,7 @@ void item::final_info( std::vector &info, const iteminfo_query *parts, } } if( parts->test( iteminfo_parts::DESCRIPTION_BREWABLE_PRODUCTS ) ) { - for( const std::string &res : brewed.brewing_results() ) { + for( const itype_id &res : brewed.brewing_results() ) { info.push_back( iteminfo( "DESCRIPTION", string_format( _( "* Fermenting this will produce " "%s." ), @@ -3656,10 +3672,13 @@ void item::final_info( std::vector &info, const iteminfo_query *parts, if( item_note != item_vars.end() && parts->test( iteminfo_parts::DESCRIPTION_NOTES ) ) { insert_separation_line( info ); std::string ntext; - const use_function *use_func = item_note_tool != item_vars.end() ? - item_controller->find_template( item_note_tool->second )->get_use( "inscribe" ) : nullptr; - const inscribe_actor *use_actor = use_func ? - dynamic_cast( use_func->get_actor_ptr() ) : nullptr; + const use_function *use_func = + item_note_tool != item_vars.end() ? + item_controller->find_template( + itype_id( item_note_tool->second ) )->get_use( "inscribe" ) : + nullptr; + const inscribe_actor *use_actor = + use_func ? dynamic_cast( use_func->get_actor_ptr() ) : nullptr; if( use_actor ) { //~ %1$s: gerund (e.g. carved), %2$s: item name, %3$s: inscription text ntext = string_format( pgettext( "carving", "%1$s on the %2$s is: %3$s" ), @@ -4281,7 +4300,7 @@ std::string item::tname( unsigned int quantity, bool with_prefix, unsigned int t } std::string maintext; - if( is_corpse() || typeId() == "blood" || item_vars.find( "name" ) != item_vars.end() ) { + if( is_corpse() || typeId() == itype_blood || item_vars.find( "name" ) != item_vars.end() ) { maintext = type_name( quantity ); } else if( is_gun() || is_tool() || is_magazine() ) { int amt = 0; @@ -4393,7 +4412,7 @@ std::string item::tname( unsigned int quantity, bool with_prefix, unsigned int t } if( has_var( "NANOFAB_ITEM_ID" ) ) { - tagtext += string_format( " (%s)", nname( get_var( "NANOFAB_ITEM_ID" ) ) ); + tagtext += string_format( " (%s)", nname( itype_id( get_var( "NANOFAB_ITEM_ID" ) ) ) ); } if( has_flag( flag_RADIO_MOD ) ) { @@ -4420,8 +4439,8 @@ std::string item::tname( unsigned int quantity, bool with_prefix, unsigned int t tagtext += _( " (lit)" ); } else if( has_flag( flag_IS_UPS ) && get_var( "cable" ) == "plugged_in" ) { tagtext += _( " (plugged in)" ); - } else if( active && !is_food() && !is_corpse() && ( typeId().length() < 3 || - typeId().compare( typeId().length() - 3, 3, "_on" ) != 0 ) ) { + } else if( active && !is_food() && !is_corpse() && + !string_ends_with( typeId().str(), "_on" ) ) { // Usually the items whose ids end in "_on" have the "active" or "on" string already contained // in their name, also food is active while it rots. tagtext += _( " (active)" ); @@ -4432,7 +4451,7 @@ std::string item::tname( unsigned int quantity, bool with_prefix, unsigned int t } std::string modtext; - if( gunmod_find( "barrel_small" ) ) { + if( gunmod_find( itype_barrel_small ) ) { modtext += _( "sawn-off " ); } if( has_flag( flag_DIAMOND ) ) { @@ -4518,7 +4537,7 @@ std::string item::display_name( unsigned int quantity ) const std::string ammotext; if( ( ( is_gun() && ammo_required() ) || is_magazine() ) && get_option( "AMMO_IN_NAMES" ) ) { - if( ammo_current() != "null" ) { + if( !ammo_current().is_null() ) { ammotext = find_type( ammo_current() )->ammo->type->name(); } else { ammotext = ammotype( *ammo_types().begin() )->name(); @@ -4661,7 +4680,7 @@ units::mass item::weight( bool, bool integral ) const } } else if( magazine_integral() && !is_magazine() ) { - if( ammo_current() == "plut_cell" ) { + if( ammo_current() == itype_plut_cell ) { ret += ammo_remaining() * find_type( ammotype( *ammo_types().begin() )->default_ammotype() )->weight / PLUTONIUM_CHARGES; } else if( ammo_data() ) { @@ -4677,7 +4696,7 @@ units::mass item::weight( bool, bool integral ) const } // reduce weight for sawn-off weapons capped to the apportioned weight of the barrel - if( gunmod_find( "barrel_small" ) ) { + if( gunmod_find( itype_barrel_small ) ) { const units::volume b = type->gun->barrel_length; const units::mass max_barrel_weight = units::from_gram( to_milliliter( b ) ); const units::mass barrel_weight = units::from_gram( b.value() * type->weight.value() / @@ -4789,7 +4808,7 @@ units::volume item::volume( bool integral ) const units::quantity num = ret * static_cast ( charges ); if( type->stack_size <= 0 ) { - debugmsg( "Item type %s has invalid stack_size %d", typeId(), type->stack_size ); + debugmsg( "Item type %s has invalid stack_size %d", typeId().str(), type->stack_size ); ret = num; } else { ret = num / type->stack_size; @@ -4828,7 +4847,7 @@ units::volume item::volume( bool integral ) const } } - if( gunmod_find( "barrel_small" ) ) { + if( gunmod_find( itype_barrel_small ) ) { ret -= type->gun->barrel_length; } } @@ -6439,7 +6458,7 @@ bool item::is_reloadable_helper( const itype_id &ammo, bool now ) const if( !is_reloadable() ) { return false; } else if( magazine_integral() ) { - if( !ammo.empty() ) { + if( !ammo.is_empty() ) { if( ammo_data() ) { if( ammo_current() != ammo ) { return false; @@ -6454,7 +6473,7 @@ bool item::is_reloadable_helper( const itype_id &ammo, bool now ) const } return now ? ( ammo_remaining() < ammo_capacity() ) : true; } else { - return ammo.empty() ? true : magazine_compatible().count( ammo ); + return ammo.is_empty() ? true : magazine_compatible().count( ammo ); } } @@ -6735,7 +6754,7 @@ gun_type_type item::gun_type() const // TODO: move to JSON and remove extraction of this from "GUN" (via skill id) //and from "GUNMOD" (via "mod_targets") in lang/extract_json_strings.py if( gun_skill() == skill_archery ) { - if( ammo_types().count( ammotype( "bolt" ) ) || typeId() == "bullet_crossbow" ) { + if( ammo_types().count( ammotype( "bolt" ) ) || typeId() == itype_bullet_crossbow ) { return gun_type_type( translate_marker_context( "gun_type_type", "crossbow" ) ); } else { return gun_type_type( translate_marker_context( "gun_type_type", "bow" ) ); @@ -6932,7 +6951,7 @@ int item::ammo_remaining() const if( is_tool() ) { // dirty hack for UPS, hopefully temporary - if( typeId() == "UPS_off" || typeId() == "adv_UPS_off" ) { + if( typeId() == itype_UPS_off || typeId() == itype_adv_UPS_off ) { return charges; } @@ -6982,7 +7001,7 @@ int item::ammo_capacity( bool potential_capacity ) const if( is_tool() ) { res = type->tool->max_charges; - if( res == 0 && magazine_default() != "null" && potential_capacity ) { + if( res == 0 && !magazine_default().is_null() && potential_capacity ) { res = find_type( magazine_default() )->magazine->capacity; } for( const item *e : toolmods() ) { @@ -7101,7 +7120,7 @@ const itype *item::ammo_data() const auto mods = is_gun() ? gunmods() : toolmods(); for( const item *e : mods ) { - if( !e->type->mod->ammo_modifier.empty() && e->ammo_current() != "null" && + if( !e->type->mod->ammo_modifier.empty() && !e->ammo_current().is_null() && item_controller->has_template( e->ammo_current() ) ) { return item_controller->find_template( e->ammo_current() ); } @@ -7116,7 +7135,7 @@ const itype *item::ammo_data() const itype_id item::ammo_current() const { const itype *ammo = ammo_data(); - return ammo ? ammo->get_id() : "null"; + return ammo ? ammo->get_id() : itype_id::NULL_ID(); } const std::set &item::ammo_types( bool conversion ) const @@ -7154,11 +7173,11 @@ itype_id item::ammo_default( bool conversion ) const { if( !ammo_types( conversion ).empty() ) { itype_id res = ammotype( *ammo_types( conversion ).begin() )->default_ammotype(); - if( !res.empty() ) { + if( !res.is_empty() ) { return res; } } - return "NULL"; + return itype_id::NULL_ID(); } itype_id item::common_ammo_default( bool conversion ) const @@ -7168,13 +7187,13 @@ itype_id item::common_ammo_default( bool conversion ) const const item *mag = magazine_current(); if( mag && mag->type->magazine->type.count( at ) ) { itype_id res = at->default_ammotype(); - if( !res.empty() ) { + if( !res.is_empty() ) { return res; } } } } - return "NULL"; + return itype_id::NULL_ID(); } std::set item::ammo_effects( bool with_ammo ) const @@ -7242,7 +7261,7 @@ itype_id item::magazine_default( bool conversion ) const return mag->second; } } - return "null"; + return itype_id::NULL_ID(); } std::set item::magazine_compatible( bool conversion ) const @@ -7330,10 +7349,11 @@ ret_val item::is_gunmod_compatible( const item &mod ) const mod.type->gunmod->location.name() ); } else if( !mod.type->gunmod->usable.count( gun_type() ) && - !mod.type->gunmod->usable.count( typeId() ) ) { + !mod.type->gunmod->usable.count( typeId().str() ) ) { return ret_val::make_failure( _( "cannot have a %s" ), mod.tname() ); - } else if( typeId() == "hand_crossbow" && !mod.type->gunmod->usable.count( pistol_gun_type ) ) { + } else if( typeId() == itype_hand_crossbow && + !mod.type->gunmod->usable.count( pistol_gun_type ) ) { return ret_val::make_failure( _( "isn't big enough to use that mod" ) ); } else if( mod.type->gunmod->location.str() == "underbarrel" && @@ -7351,13 +7371,13 @@ ret_val item::is_gunmod_compatible( const item &mod ) const return ret_val::make_failure( _( "%1$s cannot be used on item with no compatible ammo types" ), mod.tname( 1 ) ); } - } else if( mod.typeId() == "waterproof_gunmod" && has_flag( flag_WATERPROOF_GUN ) ) { + } else if( mod.typeId() == itype_waterproof_gunmod && has_flag( flag_WATERPROOF_GUN ) ) { return ret_val::make_failure( _( "is already waterproof" ) ); - } else if( mod.typeId() == "tuned_mechanism" && has_flag( flag_NEVER_JAMS ) ) { + } else if( mod.typeId() == itype_tuned_mechanism && has_flag( flag_NEVER_JAMS ) ) { return ret_val::make_failure( _( "is already eminently reliable" ) ); - } else if( mod.typeId() == "brass_catcher" && has_flag( flag_RELOAD_EJECT ) ) { + } else if( mod.typeId() == itype_brass_catcher && has_flag( flag_RELOAD_EJECT ) ) { return ret_val::make_failure( _( "cannot have a brass catcher" ) ); } else if( ( mod.type->mod->ammo_modifier.empty() || !mod.type->mod->magazine_adaptor.empty() ) @@ -7531,7 +7551,7 @@ int item::units_remaining( const Character &ch, int limit ) const int res = ammo_remaining(); if( res < limit && has_flag( flag_USE_UPS ) ) { - res += ch.charges_of( "UPS", limit - res ); + res += ch.charges_of( itype_UPS, limit - res ); } return std::min( static_cast( res ), limit ); @@ -7888,7 +7908,7 @@ bool item::flammable( int threshold ) const itype_id item::typeId() const { - return type ? type->get_id() : "null"; + return type ? type->get_id() : itype_id::NULL_ID(); } bool item::getlight( float &luminance, int &width, int &direction ) const @@ -8010,7 +8030,7 @@ bool item::use_amount( const itype_id &it, int &quantity, std::list &used, bool item::use_amount_internal( const itype_id &it, int &quantity, std::list &used, const std::function &filter ) { - if( typeId() == "null" ) { + if( typeId().is_null() ) { return false; } if( typeId() == it && quantity > 0 && filter( *this ) ) { @@ -8544,7 +8564,7 @@ uint64_t item::make_component_hash() const // First we need to sort the IDs so that identical ingredients give identical hashes. std::multiset id_set; for( const item &it : components ) { - id_set.insert( it.typeId() ); + id_set.insert( it.typeId().str() ); } std::string concatenated_ids; @@ -9123,12 +9143,12 @@ bool item::process_litcig( player *carrier, const tripoint &pos ) if( carrier != nullptr ) { carrier->add_msg_if_player( m_neutral, _( "You finish your %s." ), tname() ); } - if( typeId() == "cig_lit" ) { - convert( "cig_butt" ); - } else if( typeId() == "cigar_lit" ) { - convert( "cigar_butt" ); + if( typeId() == itype_cig_lit ) { + convert( itype_cig_butt ); + } else if( typeId() == itype_cigar_lit ) { + convert( itype_cigar_butt ); } else { // joint - convert( "joint_roach" ); + convert( itype_joint_roach ); if( carrier != nullptr ) { carrier->add_effect( effect_weed_high, 1_minutes ); // one last puff g->m.add_field( pos + point( rng( -1, 1 ), rng( -1, 1 ) ), fd_weedsmoke, 2 ); @@ -9202,12 +9222,12 @@ bool item::process_extinguish( player *carrier, const tripoint &pos ) // cig dies out if( has_flag( flag_LITCIG ) ) { - if( typeId() == "cig_lit" ) { - convert( "cig_butt" ); - } else if( typeId() == "cigar_lit" ) { - convert( "cigar_butt" ); + if( typeId() == itype_cig_lit ) { + convert( itype_cig_butt ); + } else if( typeId() == itype_cigar_lit ) { + convert( itype_cigar_butt ); } else { // joint - convert( "joint_roach" ); + convert( itype_joint_roach ); } } else { // transform (lit) items if( type->tool->revert_to ) { @@ -9365,7 +9385,7 @@ bool item::process_tool( player *carrier, const tripoint &pos ) // for items in player possession if insufficient charges within tool try UPS if( carrier && has_flag( flag_USE_UPS ) ) { - if( carrier->use_charges_if_avail( "UPS", energy ) ) { + if( carrier->use_charges_if_avail( itype_UPS, energy ) ) { energy = 0; } } @@ -9635,7 +9655,7 @@ std::string item::type_name( unsigned int quantity ) const { const auto iter = item_vars.find( "name" ); std::string ret_name; - if( typeId() == "blood" ) { + if( typeId() == itype_blood ) { if( corpse == nullptr || corpse->id.is_null() ) { return npgettext( "item name", "human blood", "human blood", quantity ); } else { @@ -9655,7 +9675,7 @@ std::string item::type_name( unsigned int quantity ) const std::function )> component_id_contains = [&]( std::list components ) { for( const item &component : components ) { - if( component.typeId().find( cname.condition ) != std::string::npos || + if( component.typeId().str().find( cname.condition ) != std::string::npos || component_id_contains( component.components ) ) { return true; } diff --git a/src/item.h b/src/item.h index d5c83542af22a..e5a6324a1d03f 100644 --- a/src/item.h +++ b/src/item.h @@ -66,8 +66,6 @@ enum body_part : int; enum m_size : int; enum class side : int; class body_part_set; - -using itype_id = std::string; class map; struct damage_instance; struct damage_unit; @@ -198,6 +196,13 @@ class item : public visitable /** For constructing in-progress crafts */ item( const recipe *rec, int qty, std::list items, std::vector selections ); + // Legacy constructor for constructing from string rather than itype_id + // TODO: remove this and migrate code using it. + template + item( const std::string &itype, Args &&... args ) : + item( itype_id( itype ), std::forward( args )... ) + {} + ~item(); /** Return a pointer-like type that's automatically invalidated if this @@ -1739,9 +1744,10 @@ class item : public visitable * @return ammotype of ammo item or a null id if the item is not ammo */ ammotype ammo_type() const; - /** Get default ammo used by item or "NULL" if item does not have a default ammo type + /** Get default ammo used by item or a null id if item does not have a default ammo type * @param conversion whether to include the effect of any flags or mods which convert the type - * @return NULL if item does not use a specific ammo type (and is consequently not reloadable) */ + * @return itype_id::NULL_ID() if item does not use a specific ammo type + * (and is consequently not reloadable) */ itype_id ammo_default( bool conversion = true ) const; /** Get default ammo for the first ammotype common to an item and its current magazine or "NULL" if none exists diff --git a/src/item_contents.h b/src/item_contents.h index 50f6df91d62e6..ba3c2ed66ace8 100644 --- a/src/item_contents.h +++ b/src/item_contents.h @@ -23,9 +23,6 @@ class JsonIn; class JsonOut; class item; struct tripoint; - -using itype_id = std::string; - class item; class item_location; class player; diff --git a/src/item_factory.cpp b/src/item_factory.cpp index 80f58c115f070..11cf03301b63a 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -55,19 +55,27 @@ class player; struct tripoint; -using t_string_set = std::set; -static t_string_set item_blacklist; +static std::set item_blacklist; static DynamicDataLoader::deferred_json deferred; std::unique_ptr item_controller = std::make_unique(); +/** @relates string_id */ +template<> +const itype &string_id::obj() const +{ + const itype *result = item_controller->find_template( *this ); + static const itype dummy{}; + return result ? *result : dummy; +} + static item_category_id calc_category( const itype &obj ); static void set_allergy_flags( itype &item_template ); static void hflesh_to_flesh( itype &item_template ); static void npc_implied_flags( itype &item_template ); -bool item_is_blacklisted( const std::string &id ) +bool item_is_blacklisted( const itype_id &id ) { return item_blacklist.count( id ); } @@ -179,7 +187,7 @@ void Item_factory::finalize_pre( itype &obj ) if( obj.stack_size == 0 ) { obj.stack_size = obj.charges_default(); } else if( obj.stack_size > 200 ) { - debugmsg( obj.id + " stack size is too large, reducing to 200" ); + debugmsg( obj.id.str() + " stack size is too large, reducing to 200" ); obj.stack_size = 200; } } @@ -243,7 +251,7 @@ void Item_factory::finalize_pre( itype &obj ) if( obj.magazine ) { // ensure default_ammo is set - if( obj.magazine->default_ammo == "NULL" ) { + if( obj.magazine->default_ammo.is_null() ) { obj.magazine->default_ammo = ammotype( *obj.magazine->type.begin() )->default_ammotype(); } @@ -413,7 +421,7 @@ void Item_factory::finalize_pre( itype &obj ) } if( obj.tool ) { - if( !obj.tool->subtype.empty() && has_template( obj.tool->subtype ) ) { + if( !obj.tool->subtype.is_empty() && has_template( obj.tool->subtype ) ) { tool_subtypes[ obj.tool->subtype ].insert( obj.id ); } } @@ -443,10 +451,10 @@ void Item_factory::finalize_pre( itype &obj ) } if( obj.can_use( "MA_MANUAL" ) && obj.book && obj.book->martial_art.is_null() && - string_starts_with( obj.get_id(), "manual_" ) ) { + string_starts_with( obj.get_id().str(), "manual_" ) ) { // HACK: Legacy martial arts books rely on a hack whereby the name of the // martial art is derived from the item id - obj.book->martial_art = matype_id( "style_" + obj.get_id().substr( 7 ) ); + obj.book->martial_art = matype_id( "style_" + obj.get_id().str().substr( 7 ) ); } if( obj.longest_side == -1_mm ) { @@ -517,7 +525,8 @@ void Item_factory::finalize_post( itype &obj ) for( const std::pair elem : obj.comestible->contamination ) { const diseasetype_id dtype = elem.first; if( !dtype.is_valid() ) { - debugmsg( "contamination in %s contains invalid diseasetype_id %s.", obj.id, dtype.c_str() ); + debugmsg( "contamination in %s contains invalid diseasetype_id %s.", + obj.id.str(), dtype.str() ); } } } @@ -564,7 +573,7 @@ void Item_factory::finalize() void Item_factory::finalize_item_blacklist() { - for( const std::string &blackout : item_blacklist ) { + for( const itype_id &blackout : item_blacklist ) { std::unordered_map::iterator candidate = m_templates.find( blackout ); if( candidate == m_templates.end() ) { debugmsg( "item on blacklist %s does not exist", blackout.c_str() ); @@ -626,8 +635,8 @@ void Item_factory::finalize_item_blacklist() if( replacement->second.ammo ) { migrated_ammo.emplace( std::make_pair( migrate.first, replacement->second.ammo->type ) ); } else { - debugmsg( "Replacement item %s for migrated ammo %s is not ammo.", migrate.second.replace, - migrate.first ); + debugmsg( "Replacement item %s for migrated ammo %s is not ammo.", + migrate.second.replace.str(), migrate.first.str() ); } } @@ -638,8 +647,8 @@ void Item_factory::finalize_item_blacklist() if( replacement->second.magazine ) { migrated_magazines.emplace( std::make_pair( migrate.first, migrate.second.replace ) ); } else { - debugmsg( "Replacement item %s for migrated magazine %s is not a magazine.", migrate.second.replace, - migrate.first ); + debugmsg( "Replacement item %s for migrated magazine %s is not a magazine.", + migrate.second.replace.str(), migrate.first.str() ); } } } @@ -659,7 +668,7 @@ void Item_factory::finalize_item_blacklist() void Item_factory::load_item_blacklist( const JsonObject &json ) { - add_array_to_set( item_blacklist, json, "items" ); + json.read( "items", item_blacklist, true ); } Item_factory::~Item_factory() = default; @@ -1058,7 +1067,7 @@ void Item_factory::check_definitions() const } } if( type->default_container && !has_template( *type->default_container ) ) { - if( *type->default_container != "null" ) { + if( !type->default_container->is_null() ) { msg += string_format( "invalid container property %s\n", type->default_container->c_str() ); } } @@ -1076,7 +1085,7 @@ void Item_factory::check_definitions() const } if( type->comestible ) { - if( type->comestible->tool != "null" ) { + if( !type->comestible->tool.is_null() ) { auto req_tool = find_template( type->comestible->tool ); if( !req_tool->tool ) { msg += string_format( "invalid tool property %s\n", type->comestible->tool.c_str() ); @@ -1131,10 +1140,10 @@ void Item_factory::check_definitions() const } check_ammo_type( msg, type->ammo->type ); if( type->ammo->casing && ( !has_template( *type->ammo->casing ) || - *type->ammo->casing == "null" ) ) { + type->ammo->casing->is_null() ) ) { msg += string_format( "invalid casing property %s\n", type->ammo->casing->c_str() ); } - if( type->ammo->drop != "null" && !has_template( type->ammo->drop ) ) { + if( !type->ammo->drop.is_null() && !has_template( type->ammo->drop ) ) { msg += string_format( "invalid drop item %s\n", type->ammo->drop.c_str() ); } } @@ -1212,7 +1221,7 @@ void Item_factory::check_definitions() const for( const itype_id &opt : e.second ) { const itype *mag = find_template( opt ); if( !mag->magazine || !mag->magazine->type.count( e.first ) ) { - msg += string_format( "invalid magazine %s in magazine adapter\n", opt ); + msg += string_format( "invalid magazine %s in magazine adapter\n", opt.str() ); } } } @@ -1232,7 +1241,7 @@ void Item_factory::check_definitions() const } const itype *da = find_template( type->magazine->default_ammo ); if( !( da->ammo && type->magazine->type.count( da->ammo->type ) ) ) { - msg += string_format( "invalid default_ammo %s\n", type->magazine->default_ammo.c_str() ); + msg += string_format( "invalid default_ammo %s\n", type->magazine->default_ammo.str() ); } if( type->magazine->reliability < 0 || type->magazine->reliability > 100 ) { msg += string_format( "invalid reliability %i\n", type->magazine->reliability ); @@ -1241,30 +1250,33 @@ void Item_factory::check_definitions() const msg += string_format( "invalid reload_time %i\n", type->magazine->reload_time ); } if( type->magazine->linkage && ( !has_template( *type->magazine->linkage ) || - *type->magazine->linkage == "null" ) ) { + type->magazine->linkage->is_null() ) ) { msg += string_format( "invalid linkage property %s\n", type->magazine->linkage->c_str() ); } } - for( const std::pair, std::set> &ammo_variety : + for( const std::pair, std::set> &ammo_variety : type->magazines ) { if( ammo_variety.second.empty() ) { msg += string_format( "no magazine specified for %s\n", ammo_variety.first.str() ); } - for( const std::string &magazine : ammo_variety.second ) { + for( const itype_id &magazine : ammo_variety.second ) { const itype *mag_ptr = find_template( magazine ); if( mag_ptr == nullptr ) { - msg += string_format( "magazine \"%s\" specified for \"%s\" does not exist\n", magazine, - ammo_variety.first.str() ); + msg += string_format( "magazine \"%s\" specified for \"%s\" does not exist\n", + magazine.str(), ammo_variety.first.str() ); } else if( !mag_ptr->magazine ) { - msg += string_format( "magazine \"%s\" specified for \"%s\" is not a magazine\n", magazine, - ammo_variety.first.str() ); + msg += string_format( + "magazine \"%s\" specified for \"%s\" is not a magazine\n", magazine.str(), + ammo_variety.first.str() ); } else if( !mag_ptr->magazine->type.count( ammo_variety.first ) ) { - msg += string_format( "magazine \"%s\" does not take compatible ammo\n", magazine ); + msg += string_format( "magazine \"%s\" does not take compatible ammo\n", + magazine.str() ); } else if( mag_ptr->item_tags.count( "SPEEDLOADER" ) && mag_ptr->magazine->capacity != type->gun->clip ) { - msg += string_format( "speedloader %s capacity (%d) does not match gun capacity (%d).\n", magazine, - mag_ptr->magazine->capacity, type->gun->clip ); + msg += string_format( + "speedloader %s capacity (%d) does not match gun capacity (%d).\n", + magazine.str(), mag_ptr->magazine->capacity, type->gun->clip ); } } } @@ -1274,14 +1286,14 @@ void Item_factory::check_definitions() const check_ammo_type( msg, at ); } if( type->tool->revert_to && ( !has_template( *type->tool->revert_to ) || - *type->tool->revert_to == "null" ) ) { + type->tool->revert_to->is_null() ) ) { msg += string_format( "invalid revert_to property %s\n", type->tool->revert_to->c_str() ); } if( !type->tool->revert_msg.empty() && !type->tool->revert_to ) { msg += "cannot specify revert_msg without revert_to\n"; } - if( !type->tool->subtype.empty() && !has_template( type->tool->subtype ) ) { - msg += string_format( "invalid tool subtype %s\n", type->tool->subtype ); + if( !type->tool->subtype.is_empty() && !has_template( type->tool->subtype ) ) { + msg += string_format( "invalid tool subtype %s\n", type->tool->subtype.str() ); } } if( type->bionic ) { @@ -1361,7 +1373,7 @@ const itype *Item_factory::find_template( const itype_id &id ) const return def; } -Item_spawn_data *Item_factory::get_group( const Item_tag &group_tag ) +Item_spawn_data *Item_factory::get_group( const Group_tag &group_tag ) { GroupMap::iterator group_iter = m_template_groups.find( group_tag ); if( group_iter != m_template_groups.end() ) { @@ -1423,19 +1435,21 @@ bool Item_factory::load_definition( const JsonObject &jo, const std::string &src return true; } - auto base = m_templates.find( jo.get_string( "copy-from" ) ); + itype_id copy_from; + jo.read( "copy-from", copy_from, true ); + auto base = m_templates.find( copy_from ); if( base != m_templates.end() ) { def = base->second; - def.looks_like = jo.get_string( "copy-from" ); + def.looks_like = copy_from; def.was_loaded = true; return true; } - auto abstract = m_abstracts.find( jo.get_string( "copy-from" ) ); + auto abstract = m_abstracts.find( copy_from ); if( abstract != m_abstracts.end() ) { def = abstract->second; - if( def.looks_like.empty() ) { - def.looks_like = jo.get_string( "copy-from" ); + if( def.looks_like.is_empty() ) { + def.looks_like = copy_from; } def.was_loaded = true; return true; @@ -1467,7 +1481,7 @@ void islot_ammo::load( const JsonObject &jo ) { mandatory( jo, was_loaded, "ammo_type", type ); optional( jo, was_loaded, "casing", casing, cata::nullopt ); - optional( jo, was_loaded, "drop", drop, "null" ); + optional( jo, was_loaded, "drop", drop, itype_id::NULL_ID() ); optional( jo, was_loaded, "drop_chance", drop_chance, 1.0f ); optional( jo, was_loaded, "drop_active", drop_active, true ); // Damage instance assign reader handles pierce and prop_damage @@ -1770,7 +1784,7 @@ void Item_factory::load( islot_mod &slot, const JsonObject &jo, const std::strin ammotype ammo( arr.get_string( 0 ) ); // an ammo type (e.g. 9mm) // compatible magazines for this ammo type for( const std::string line : arr.get_array( 1 ) ) { - slot.magazine_adaptor[ ammo ].insert( line ); + slot.magazine_adaptor[ ammo ].insert( itype_id( line ) ); } } } @@ -1962,7 +1976,7 @@ void Item_factory::load( islot_comestible &slot, const JsonObject &jo, const std void Item_factory::load( islot_brewable &slot, const JsonObject &jo, const std::string & ) { assign( jo, "time", slot.time, false, 1_turns ); - slot.results = jo.get_string_array( "results" ); + jo.read( "results", slot.results, true ); } void Item_factory::load_comestible( const JsonObject &jo, const std::string &src ) @@ -2370,10 +2384,10 @@ void Item_factory::load_basic_info( const JsonObject &jo, itype &def, const std: JsonArray compat = arr.get_array( 1 ); // compatible magazines for this ammo type // the first magazine for this ammo type is the default - def.magazine_default[ ammo ] = compat.get_string( 0 ); + def.magazine_default[ ammo ] = itype_id( compat.get_string( 0 ) ); while( compat.has_more() ) { - def.magazines[ ammo ].insert( compat.next_string() ); + def.magazines[ ammo ].insert( itype_id( compat.next_string() ) ); } } } @@ -2491,16 +2505,16 @@ void Item_factory::load_basic_info( const JsonObject &jo, itype &def, const std: add_special_pockets( def ); if( jo.has_string( "abstract" ) ) { - def.id = jo.get_string( "abstract" ); + jo.read( "abstract", def.id, true ); } else { - def.id = jo.get_string( "id" ); + jo.read( "id", def.id, true ); } // snippet_category should be loaded after def.id is determined if( jo.has_array( "snippet_category" ) ) { // auto-create a category that is unlikely to already be used and put the // snippets in it. - def.snippet_category = std::string( "auto:" ) + def.id; + def.snippet_category = "auto:" + def.id.str(); SNIPPET.add_snippets_from_json( def.snippet_category, jo.get_array( "snippet_category" ) ); } else { def.snippet_category = jo.get_string( "snippet_category", "" ); @@ -2522,11 +2536,13 @@ void Item_factory::load_migration( const JsonObject &jo ) assign( jo, "contents", m.contents ); if( jo.has_string( "id" ) ) { - m.id = jo.get_string( "id" ); + jo.read( "id", m.id, true ); migrations[ m.id ] = m; } else if( jo.has_array( "id" ) ) { - for( const std::string line : jo.get_array( "id" ) ) { - m.id = line; + std::vector ids; + jo.read( "id", ids, true ); + for( const itype_id id : ids ) { + m.id = id; migrations[ m.id ] = m; } } else { @@ -2732,7 +2748,7 @@ bool Item_factory::load_sub_ref( std::unique_ptr &ptr, const Js if( elem.second ) { result->add_group_entry( elem.first, prob ); } else { - result->add_item_entry( elem.first, prob ); + result->add_item_entry( itype_id( elem.first ), prob ); } } return true; @@ -2812,7 +2828,7 @@ void Item_factory::add_entry( Item_group &ig, const JsonObject &obj ) // Load an item group from JSON void Item_factory::load_item_group( const JsonObject &jsobj ) { - const Item_tag group_id = jsobj.get_string( "id" ); + const Group_tag group_id = jsobj.get_string( "id" ); const std::string subtype = jsobj.get_string( "subtype", "old" ); load_item_group( jsobj, group_id, subtype ); } @@ -2850,7 +2866,7 @@ void Item_factory::load_item_group( const JsonObject &jsobj, const Group_tag &gr add_entry( *ig, subobj ); } else { JsonArray pair = entry.get_array(); - ig->add_item_entry( pair.get_string( 0 ), pair.get_int( 1 ) ); + ig->add_item_entry( itype_id( pair.get_string( 0 ) ), pair.get_int( 1 ) ); } } return; @@ -2864,10 +2880,10 @@ void Item_factory::load_item_group( const JsonObject &jsobj, const Group_tag &gr if( jsobj.has_member( "items" ) ) { for( const JsonValue entry : jsobj.get_array( "items" ) ) { if( entry.test_string() ) { - ig->add_item_entry( entry.get_string(), 100 ); + ig->add_item_entry( itype_id( entry.get_string() ), 100 ); } else if( entry.test_array() ) { JsonArray subitem = entry.get_array(); - ig->add_item_entry( subitem.get_string( 0 ), subitem.get_int( 1 ) ); + ig->add_item_entry( itype_id( subitem.get_string( 0 ) ), subitem.get_int( 1 ) ); } else { JsonObject subobj = entry.get_object(); add_entry( *ig, subobj ); @@ -3044,7 +3060,7 @@ std::vector Item_factory::get_all_group_names() return rval; } -bool Item_factory::add_item_to_group( const Group_tag &group_id, const Item_tag &item_id, +bool Item_factory::add_item_to_group( const Group_tag &group_id, const itype_id &item_id, int chance ) { if( m_template_groups.find( group_id ) == m_template_groups.end() ) { @@ -3149,13 +3165,13 @@ std::vector Item_factory::find( const std::function class value_ptr; } // namespace cata -bool item_is_blacklisted( const std::string &id ); +bool item_is_blacklisted( const itype_id &id ); -using Item_tag = std::string; using Group_tag = std::string; +using item_action_id = std::string; using Item_list = std::vector; class Item_factory; @@ -41,11 +41,11 @@ extern std::unique_ptr item_controller; class migration { public: - std::string id; - std::string replace; + itype_id id; + itype_id replace; std::set flags; int charges = 0; - std::set contents; + std::set contents; }; /** @@ -137,7 +137,7 @@ class Item_factory * group. * @return false if the group doesn't exist. */ - bool add_item_to_group( const Group_tag &group_id, const Item_tag &item_id, int chance ); + bool add_item_to_group( const Group_tag &group_id, const itype_id &item_id, int chance ); /*@}*/ /** @@ -220,7 +220,7 @@ class Item_factory * Check if an iuse is known to the Item_factory. * @param type Iuse type id. */ - bool has_iuse( const std::string &type ) const { + bool has_iuse( const item_action_id &type ) const { return iuse_function_list.find( type ) != iuse_function_list.end(); } @@ -238,7 +238,7 @@ class Item_factory /** * Create a new (and currently unused) item type id. */ - Item_tag create_artifact_id() const; + itype_id create_artifact_id() const; std::list subtype_replacement( const itype_id & ) const; @@ -246,7 +246,7 @@ class Item_factory /** Set at finalization and prevents alterations to the static item templates */ bool frozen = false; - std::map m_abstracts; + std::map m_abstracts; std::unordered_map m_templates; @@ -350,7 +350,7 @@ class Item_factory void finalize_post( itype &obj ); //iuse stuff - std::map iuse_function_list; + std::map iuse_function_list; void add_iuse( const std::string &type, use_function_pointer f ); void add_iuse( const std::string &type, use_function_pointer f, diff --git a/src/item_group.cpp b/src/item_group.cpp index 8c984121dae42..1be619eca5793 100644 --- a/src/item_group.cpp +++ b/src/item_group.cpp @@ -123,7 +123,7 @@ Item_spawn_data::ItemList Single_item_creator::create( const time_point &birthda void Single_item_creator::check_consistency( const std::string &context ) const { if( type == S_ITEM ) { - if( !item::type_is_defined( id ) ) { + if( !item::type_is_defined( itype_id( id ) ) ) { debugmsg( "item id %s is unknown (in %s)", id, context ); } } else if( type == S_ITEM_GROUP ) { @@ -140,7 +140,7 @@ void Single_item_creator::check_consistency( const std::string &context ) const } } -bool Single_item_creator::remove_item( const Item_tag &itemid ) +bool Single_item_creator::remove_item( const itype_id &itemid ) { if( modifier ) { if( modifier->remove_item( itemid ) ) { @@ -149,7 +149,7 @@ bool Single_item_creator::remove_item( const Item_tag &itemid ) } } if( type == S_ITEM ) { - if( itemid == id ) { + if( itemid.str() == id ) { type = S_NONE; return true; } @@ -162,7 +162,7 @@ bool Single_item_creator::remove_item( const Item_tag &itemid ) return type == S_NONE; } -bool Single_item_creator::replace_item( const Item_tag &itemid, const Item_tag &replacementid ) +bool Single_item_creator::replace_item( const itype_id &itemid, const itype_id &replacementid ) { if( modifier ) { if( modifier->replace_item( itemid, replacementid ) ) { @@ -170,8 +170,8 @@ bool Single_item_creator::replace_item( const Item_tag &itemid, const Item_tag & } } if( type == S_ITEM ) { - if( itemid == id ) { - id = replacementid; + if( itemid.str() == id ) { + id = replacementid.str(); return true; } } else if( type == S_ITEM_GROUP ) { @@ -183,16 +183,16 @@ bool Single_item_creator::replace_item( const Item_tag &itemid, const Item_tag & return type == S_NONE; } -bool Single_item_creator::has_item( const Item_tag &itemid ) const +bool Single_item_creator::has_item( const itype_id &itemid ) const { - return type == S_ITEM && itemid == id; + return type == S_ITEM && itemid.str() == id; } std::set Single_item_creator::every_item() const { switch( type ) { case S_ITEM: - return { item::find_type( id ) }; + return { item::find_type( itype_id( id ) ) }; case S_ITEM_GROUP: { Item_spawn_data *isd = item_controller->get_group( id ); if( isd != nullptr ) { @@ -258,7 +258,7 @@ void Item_modifier::modify( item &new_item ) const } if( cont.is_null() && new_item.type->default_container.has_value() ) { const itype_id &cont_value = new_item.type->default_container.value_or( "null" ); - if( cont_value != "null" ) { + if( !cont_value.is_null() ) { cont = item( cont_value, new_item.birthday() ); } } @@ -390,7 +390,7 @@ void Item_modifier::check_consistency( const std::string &context ) const } } -bool Item_modifier::remove_item( const Item_tag &itemid ) +bool Item_modifier::remove_item( const itype_id &itemid ) { if( ammo != nullptr ) { if( ammo->remove_item( itemid ) ) { @@ -406,7 +406,7 @@ bool Item_modifier::remove_item( const Item_tag &itemid ) return false; } -bool Item_modifier::replace_item( const Item_tag &itemid, const Item_tag &replacementid ) +bool Item_modifier::replace_item( const itype_id &itemid, const itype_id &replacementid ) { if( ammo != nullptr ) { ammo->replace_item( itemid, replacementid ); @@ -437,10 +437,10 @@ Item_group::Item_group( Type t, int probability, int ammo_chance, int magazine_c } } -void Item_group::add_item_entry( const Item_tag &itemid, int probability ) +void Item_group::add_item_entry( const itype_id &itemid, int probability ) { add_entry( std::make_unique( - itemid, Single_item_creator::S_ITEM, probability ) ); + itemid.str(), Single_item_creator::S_ITEM, probability ) ); } void Item_group::add_group_entry( const Group_tag &groupid, int probability ) @@ -525,7 +525,7 @@ void Item_group::check_consistency( const std::string &context ) const } } -bool Item_group::remove_item( const Item_tag &itemid ) +bool Item_group::remove_item( const itype_id &itemid ) { for( prop_list::iterator a = items.begin(); a != items.end(); ) { if( ( *a )->remove_item( itemid ) ) { @@ -538,7 +538,7 @@ bool Item_group::remove_item( const Item_tag &itemid ) return items.empty(); } -bool Item_group::replace_item( const Item_tag &itemid, const Item_tag &replacementid ) +bool Item_group::replace_item( const itype_id &itemid, const itype_id &replacementid ) { for( const std::unique_ptr &elem : items ) { ( elem )->replace_item( itemid, replacementid ); @@ -546,7 +546,7 @@ bool Item_group::replace_item( const Item_tag &itemid, const Item_tag &replaceme return items.empty(); } -bool Item_group::has_item( const Item_tag &itemid ) const +bool Item_group::has_item( const itype_id &itemid ) const { for( const std::unique_ptr &elem : items ) { if( ( elem )->has_item( itemid ) ) { diff --git a/src/item_group.h b/src/item_group.h index 1badea4caa7bc..1288a4c186421 100644 --- a/src/item_group.h +++ b/src/item_group.h @@ -13,7 +13,6 @@ struct itype; -using Item_tag = std::string; using Group_tag = std::string; class JsonObject; class JsonValue; @@ -56,7 +55,7 @@ ItemList items_from( const Group_tag &group_id ); /** * Check whether a specific item group contains a specific item type. */ -bool group_contains_item( const Group_tag &group_id, const Item_tag &type_id ); +bool group_contains_item( const Group_tag &group_id, const itype_id & ); /** * Return every item type that can possibly be spawned by the item group */ @@ -106,7 +105,7 @@ class Item_spawn_data { public: using ItemList = std::vector; - using RecursionList = std::vector; + using RecursionList = std::vector; Item_spawn_data( int _probability ) : probability( _probability ) { } virtual ~Item_spawn_data() = default; @@ -133,9 +132,9 @@ class Item_spawn_data * For item blacklisted, remove the given item from this and * all linked groups. */ - virtual bool remove_item( const Item_tag &itemid ) = 0; - virtual bool replace_item( const Item_tag &itemid, const Item_tag &replacementid ) = 0; - virtual bool has_item( const Item_tag &itemid ) const = 0; + virtual bool remove_item( const itype_id &itemid ) = 0; + virtual bool replace_item( const itype_id &itemid, const itype_id &replacementid ) = 0; + virtual bool has_item( const itype_id &itemid ) const = 0; virtual std::set every_item() const = 0; @@ -189,8 +188,8 @@ class Item_modifier void modify( item &new_item ) const; void check_consistency( const std::string &context ) const; - bool remove_item( const Item_tag &itemid ); - bool replace_item( const Item_tag &itemid, const Item_tag &replacementid ); + bool remove_item( const itype_id &itemid ); + bool replace_item( const itype_id &itemid, const itype_id &replacementid ); // Currently these always have the same chance as the item group it's part of, but // theoretically it could be defined per-item / per-group. @@ -237,10 +236,10 @@ class Single_item_creator : public Item_spawn_data ItemList create( const time_point &birthday, RecursionList &rec ) const override; item create_single( const time_point &birthday, RecursionList &rec ) const override; void check_consistency( const std::string &context ) const override; - bool remove_item( const Item_tag &itemid ) override; - bool replace_item( const Item_tag &itemid, const Item_tag &replacementid ) override; + bool remove_item( const itype_id &itemid ) override; + bool replace_item( const itype_id &itemid, const itype_id &replacementid ) override; - bool has_item( const Item_tag &itemid ) const override; + bool has_item( const itype_id &itemid ) const override; std::set every_item() const override; }; @@ -271,7 +270,7 @@ class Item_group : public Item_spawn_data */ using prop_list = std::vector >; - void add_item_entry( const Item_tag &itemid, int probability ); + void add_item_entry( const itype_id &itemid, int probability ); void add_group_entry( const Group_tag &groupid, int probability ); /** * Once the relevant data has been read from JSON, this function is always called (either from @@ -283,9 +282,9 @@ class Item_group : public Item_spawn_data ItemList create( const time_point &birthday, RecursionList &rec ) const override; item create_single( const time_point &birthday, RecursionList &rec ) const override; void check_consistency( const std::string &context ) const override; - bool remove_item( const Item_tag &itemid ) override; - bool replace_item( const Item_tag &itemid, const Item_tag &replacementid ) override; - bool has_item( const Item_tag &itemid ) const override; + bool remove_item( const itype_id &itemid ) override; + bool replace_item( const itype_id &itemid, const itype_id &replacementid ) override; + bool has_item( const itype_id &itemid ) const override; std::set every_item() const override; /** diff --git a/src/item_pocket.cpp b/src/item_pocket.cpp index 4580e35d70da3..9f488cbe8fd83 100644 --- a/src/item_pocket.cpp +++ b/src/item_pocket.cpp @@ -1131,7 +1131,7 @@ std::list &item_pocket::edit_contents() void item_pocket::migrate_item( item &obj, const std::set &migrations ) { - for( const std::string &c : migrations ) { + for( const itype_id &c : migrations ) { if( std::none_of( contents.begin(), contents.end(), [&]( const item & e ) { return e.typeId() == c; } ) ) { diff --git a/src/item_pocket.h b/src/item_pocket.h index f344bea22e93b..6344ea276a161 100644 --- a/src/item_pocket.h +++ b/src/item_pocket.h @@ -26,8 +26,6 @@ struct iteminfo; struct itype; struct tripoint; -using itype_id = std::string; - class item_pocket { public: diff --git a/src/itype.h b/src/itype.h index 9fa08f77db13a..08315f6e7b49b 100644 --- a/src/itype.h +++ b/src/itype.h @@ -37,7 +37,6 @@ enum art_effect_active : int; enum art_charge : int; enum art_charge_req : int; enum art_effect_passive : int; -using itype_id = std::string; class gun_modifier_data { @@ -97,7 +96,7 @@ struct islot_tool { cata::optional revert_to; std::string revert_msg; - std::string subtype; + itype_id subtype; int max_charges = 0; int def_charges = 0; @@ -117,7 +116,7 @@ struct islot_comestible { std::string comesttype; /** tool needed to consume (e.g. lighter for cigarettes) */ - std::string tool = "null"; + itype_id tool = itype_id::NULL_ID(); /** Defaults # of charges (drugs, loaf of bread? etc) */ int def_charges = 1; @@ -197,7 +196,7 @@ struct islot_comestible { struct islot_brewable { /** What are the results of fermenting this item? */ - std::vector results; + std::vector results; /** How long for this brew to ferment. */ time_duration time = 0_turns; @@ -637,7 +636,7 @@ struct islot_magazine { int count = 0; /** Default type of ammo contained by a magazine (often set for ammo belts) */ - itype_id default_ammo = "NULL"; + itype_id default_ammo = itype_id::NULL_ID(); /** * How reliable this magazine on a range of 0 to 10? @@ -673,7 +672,7 @@ struct islot_ammo : common_ranged_data { /** * Control chance for and state of any items dropped at ranged target *@{*/ - itype_id drop = "null"; + itype_id drop = itype_id::NULL_ID(); float drop_chance = 1.0; @@ -766,7 +765,7 @@ struct islot_seed { /** * Type id of the fruit item. */ - std::string fruit_id; + itype_id fruit_id; /** * Whether to spawn seed items additionally to the fruit items. */ @@ -774,7 +773,7 @@ struct islot_seed { /** * Additionally items (a list of their item ids) that will spawn when harvesting the plant. */ - std::vector byproducts; + std::vector byproducts; islot_seed() = default; }; @@ -844,7 +843,7 @@ struct itype { /*@}*/ // a hint for tilesets: if it doesn't have a tile, what does it look like? - std::string looks_like; + itype_id looks_like; // What item this item repairs like if it doesn't have a recipe itype_id repairs_like; @@ -1001,7 +1000,7 @@ struct itype { /// @} protected: - std::string id = "null"; /** unique string identifier for this type */ + itype_id id = itype_id::NULL_ID(); /** unique string identifier for this type */ // private because is should only be accessed through itype::nname! // nname() is used for display purposes diff --git a/src/iuse.cpp b/src/iuse.cpp index f800f3d48bfb2..01d5e9d4802e4 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -222,6 +222,79 @@ static const efftype_id effect_weak_antibiotic_visible( "weak_antibiotic_visible static const efftype_id effect_webbed( "webbed" ); static const efftype_id effect_weed_high( "weed_high" ); +static const itype_id itype_adv_UPS_off( "adv_UPS_off" ); +static const itype_id itype_advanced_ecig( "advanced_ecig" ); +static const itype_id itype_afs_atomic_smartphone( "afs_atomic_smartphone" ); +static const itype_id itype_afs_atomic_smartphone_music( "afs_atomic_smartphone_music" ); +static const itype_id itype_afs_wraitheon_smartphone( "afs_wraitheon_smartphone" ); +static const itype_id itype_afs_atomic_wraitheon_music( "afs_atomic_wraitheon_music" ); +static const itype_id itype_apparatus( "apparatus" ); +static const itype_id itype_arrow_flamming( "arrow_flamming" ); +static const itype_id itype_atomic_coffeepot( "atomic_coffeepot" ); +static const itype_id itype_battery( "battery" ); +static const itype_id itype_barometer( "barometer" ); +static const itype_id itype_c4armed( "c4armed" ); +static const itype_id itype_canister_empty( "canister_empty" ); +static const itype_id itype_chainsaw_off( "chainsaw_off" ); +static const itype_id itype_chainsaw_on( "chainsaw_on" ); +static const itype_id itype_cig( "cig" ); +static const itype_id itype_cigar( "cigar" ); +static const itype_id itype_cow_bell( "cow_bell" ); +static const itype_id itype_data_card( "data_card" ); +static const itype_id itype_detergent( "detergent" ); +static const itype_id itype_e_handcuffs( "e_handcuffs" ); +static const itype_id itype_ecig( "ecig" ); +static const itype_id itype_fire( "fire" ); +static const itype_id itype_firecracker_act( "firecracker_act" ); +static const itype_id itype_firecracker_pack_act( "firecracker_pack_act" ); +static const itype_id itype_geiger_off( "geiger_off" ); +static const itype_id itype_geiger_on( "geiger_on" ); +static const itype_id itype_granade_act( "granade_act" ); +static const itype_id itype_handrolled_cig( "handrolled_cig" ); +static const itype_id itype_heatpack_used( "heatpack_used" ); +static const itype_id itype_hygrometer( "hygrometer" ); +static const itype_id itype_joint( "joint" ); +static const itype_id itype_log( "log" ); +static const itype_id itype_manhole_cover( "manhole_cover" ); +static const itype_id itype_mask_h20survivor_on( "mask_h20survivor_on" ); +static const itype_id itype_mininuke_act( "mininuke_act" ); +static const itype_id itype_molotov( "molotov" ); +static const itype_id itype_mobile_memory_card( "mobile_memory_card" ); +static const itype_id itype_mobile_memory_card_used( "mobile_memory_card_used" ); +static const itype_id itype_mp3( "mp3" ); +static const itype_id itype_mp3_on( "mp3_on" ); +static const itype_id itype_multi_cooker( "multi_cooker" ); +static const itype_id itype_multi_cooker_filled( "multi_cooker_filled" ); +static const itype_id itype_nicotine_liquid( "nicotine_liquid" ); +static const itype_id itype_noise_emitter( "noise_emitter" ); +static const itype_id itype_noise_emitter_on( "noise_emitter_on" ); +static const itype_id itype_radio( "radio" ); +static const itype_id itype_radio_car( "radio_car" ); +static const itype_id itype_radio_car_on( "radio_car_on" ); +static const itype_id itype_radio_on( "radio_on" ); +static const itype_id itype_rebreather_on( "rebreather_on" ); +static const itype_id itype_rebreather_xl_on( "rebreather_xl_on" ); +static const itype_id itype_rmi2_corpse( "rmi2_corpse" ); +static const itype_id itype_sheet( "sheet" ); +static const itype_id itype_shocktonfa_off( "shocktonfa_off" ); +static const itype_id itype_shocktonfa_on( "shocktonfa_on" ); +static const itype_id itype_smart_phone( "smart_phone" ); +static const itype_id itype_smartphone_music( "smartphone_music" ); +static const itype_id itype_soap( "soap" ); +static const itype_id itype_soldering_iron( "soldering_iron" ); +static const itype_id itype_spiral_stone( "spiral_stone" ); +static const itype_id itype_stick( "stick" ); +static const itype_id itype_string_36( "string_36" ); +static const itype_id itype_thermometer( "thermometer" ); +static const itype_id itype_towel( "towel" ); +static const itype_id itype_towel_soiled( "towel_soiled" ); +static const itype_id itype_towel_wet( "towel_wet" ); +static const itype_id itype_UPS_off( "UPS_off" ); +static const itype_id itype_water( "water" ); +static const itype_id itype_water_clean( "water_clean" ); +static const itype_id itype_wax( "wax" ); +static const itype_id itype_weather_reader( "weather_reader" ); + static const skill_id skill_computer( "computer" ); static const skill_id skill_cooking( "cooking" ); static const skill_id skill_electronics( "electronics" ); @@ -403,7 +476,7 @@ int iuse::sewage( player *p, item *it, bool, const tripoint & ) int iuse::honeycomb( player *p, item *it, bool, const tripoint & ) { - g->m.spawn_item( p->pos(), "wax", 2 ); + g->m.spawn_item( p->pos(), itype_wax, 2 ); return it->type->charges_to_use(); } @@ -469,7 +542,7 @@ int iuse::alcohol_strong( player *p, item *it, bool, const tripoint & ) */ int iuse::smoking( player *p, item *it, bool, const tripoint & ) { - bool hasFire = ( p->has_charges( "fire", 1 ) ); + bool hasFire = ( p->has_charges( itype_fire, 1 ) ); // make sure we're not already smoking something if( !check_litcig( *p ) ) { @@ -482,24 +555,24 @@ int iuse::smoking( player *p, item *it, bool, const tripoint & ) } item cig; - if( it->typeId() == "cig" ) { + if( it->typeId() == itype_cig ) { cig = item( "cig_lit", calendar::turn ); cig.item_counter = to_turns( 4_minutes ); p->mod_hunger( -3 ); p->mod_thirst( 2 ); - } else if( it->typeId() == "handrolled_cig" ) { + } else if( it->typeId() == itype_handrolled_cig ) { // This transforms the hand-rolled into a normal cig, which isn't exactly // what I want, but leaving it for now. cig = item( "cig_lit", calendar::turn ); cig.item_counter = to_turns( 4_minutes ); p->mod_thirst( 2 ); p->mod_hunger( -3 ); - } else if( it->typeId() == "cigar" ) { + } else if( it->typeId() == itype_cigar ) { cig = item( "cigar_lit", calendar::turn ); cig.item_counter = to_turns( 12_minutes ); p->mod_thirst( 3 ); p->mod_hunger( -4 ); - } else if( it->typeId() == "joint" ) { + } else if( it->typeId() == itype_joint ) { cig = item( "joint_lit", calendar::turn ); cig.item_counter = to_turns( 4_minutes ); p->mod_hunger( 4 ); @@ -514,13 +587,13 @@ int iuse::smoking( player *p, item *it, bool, const tripoint & ) return 0; } // If we're here, we better have a cig to light. - p->use_charges_if_avail( "fire", 1 ); + p->use_charges_if_avail( itype_fire, 1 ); cig.active = true; p->inv.add_item( cig, false, true ); p->add_msg_if_player( m_neutral, _( "You light a %s." ), cig.tname() ); // Parting messages - if( it->typeId() == "joint" ) { + if( it->typeId() == itype_joint ) { // Would group with the joint, but awkward to mutter before lighting up. if( one_in( 5 ) ) { weed_msg( *p ); @@ -536,13 +609,13 @@ int iuse::smoking( player *p, item *it, bool, const tripoint & ) int iuse::ecig( player *p, item *it, bool, const tripoint & ) { - if( it->typeId() == "ecig" ) { + if( it->typeId() == itype_ecig ) { p->add_msg_if_player( m_neutral, _( "You take a puff from your electronic cigarette." ) ); - } else if( it->typeId() == "advanced_ecig" ) { - if( p->has_charges( "nicotine_liquid", 1 ) ) { + } else if( it->typeId() == itype_advanced_ecig ) { + if( p->has_charges( itype_nicotine_liquid, 1 ) ) { p->add_msg_if_player( m_neutral, _( "You inhale some vapor from your advanced electronic cigarette." ) ); - p->use_charges( "nicotine_liquid", 1 ); + p->use_charges( itype_nicotine_liquid, 1 ); item dummy_ecig = item( "ecig", calendar::turn ); p->consume_effects( dummy_ecig ); } else { @@ -787,7 +860,7 @@ int iuse::meth( player *p, item *it, bool, const tripoint & ) { /** @EFFECT_STR reduces duration of meth */ time_duration duration = 1_minutes * ( 60 - p->str_cur ); - if( p->has_amount( "apparatus", 1 ) && p->use_charges_if_avail( "fire", 1 ) ) { + if( p->has_amount( itype_apparatus, 1 ) && p->use_charges_if_avail( itype_fire, 1 ) ) { p->add_msg_if_player( m_neutral, _( "You smoke your meth." ) ); p->add_msg_if_player( m_good, _( "The world seems to sharpen." ) ); p->mod_fatigue( -375 ); @@ -1980,7 +2053,7 @@ int iuse::rm13armor_off( player *p, item *it, bool, const tripoint & ) p->add_msg_if_player( m_info, _( "The RM13 combat armor's fuel cells are dead." ) ); return 0; } else { - std::string oname = it->typeId() + "_on"; + std::string oname = it->typeId().str() + "_on"; p->add_msg_if_player( _( "You activate your RM13 combat armor." ) ); p->add_msg_if_player( _( "Rivtech Model 13 RivOS v2.19: ONLINE." ) ); p->add_msg_if_player( _( "CBRN defense system: ONLINE." ) ); @@ -1989,7 +2062,7 @@ int iuse::rm13armor_off( player *p, item *it, bool, const tripoint & ) p->add_msg_if_player( _( "Vision enhancement system: ONLINE." ) ); p->add_msg_if_player( _( "Electro-reactive armor system: ONLINE." ) ); p->add_msg_if_player( _( "All systems nominal." ) ); - it->convert( oname ).active = true; + it->convert( itype_id( oname ) ).active = true; p->reset_encumbrance(); return it->type->charges_to_use(); } @@ -1999,8 +2072,8 @@ int iuse::rm13armor_on( player *p, item *it, bool t, const tripoint & ) { if( t ) { // Normal use } else { // Turning it off - std::string oname = it->typeId(); - if( oname.length() > 3 && oname.compare( oname.length() - 3, 3, "_on" ) == 0 ) { + std::string oname = it->typeId().str(); + if( string_ends_with( oname, "_on" ) ) { oname.erase( oname.length() - 3, 3 ); } else { debugmsg( "no item type to turn it into (%s)!", oname ); @@ -2009,7 +2082,7 @@ int iuse::rm13armor_on( player *p, item *it, bool t, const tripoint & ) p->add_msg_if_player( _( "RivOS v2.19 shutdown sequence initiated." ) ); p->add_msg_if_player( _( "Shutting down." ) ); p->add_msg_if_player( _( "Your RM13 combat armor turns off." ) ); - it->convert( oname ).active = false; + it->convert( itype_id( oname ) ).active = false; p->reset_encumbrance(); } return it->type->charges_to_use(); @@ -2021,10 +2094,10 @@ int iuse::unpack_item( player *p, item *it, bool, const tripoint & ) p->add_msg_if_player( m_info, _( "You can't do that while underwater." ) ); return 0; } - std::string oname = it->typeId() + "_on"; + std::string oname = it->typeId().str() + "_on"; p->moves -= to_moves( 10_seconds ); p->add_msg_if_player( _( "You unpack your %s for use." ), it->tname() ); - it->convert( oname ).active = false; + it->convert( itype_id( oname ) ).active = false; return 0; } @@ -2072,8 +2145,8 @@ int iuse::pack_item( player *p, item *it, bool t, const tripoint & ) it->tname() ); return 0; } else { // Turning it off - std::string oname = it->typeId(); - if( oname.length() > 3 && oname.compare( oname.length() - 3, 3, "_on" ) == 0 ) { + std::string oname = it->typeId().str(); + if( string_ends_with( oname, "_on" ) ) { oname.erase( oname.length() - 3, 3 ); } else { debugmsg( "no item type to turn it into (%s)!", oname ); @@ -2081,7 +2154,7 @@ int iuse::pack_item( player *p, item *it, bool t, const tripoint & ) } p->moves -= to_moves( 10_seconds ); p->add_msg_if_player( _( "You pack your %s for storage." ), it->tname() ); - it->convert( oname ).active = false; + it->convert( itype_id( oname ) ).active = false; } return 0; } @@ -2115,7 +2188,7 @@ int iuse::water_purifier( player *p, item *it, bool, const tripoint & ) } item_location obj = g->inv_map_splice( []( const item & e ) { return !e.contents.empty() && e.has_item_with( []( const item & it ) { - return it.typeId() == "water"; + return it.typeId() == itype_water; } ); }, _( "Purify what?" ), 1, _( "You don't have water to purify." ) ); @@ -2125,7 +2198,7 @@ int iuse::water_purifier( player *p, item *it, bool, const tripoint & ) } const std::vector liquids = obj->items_with( []( const item & it ) { - return it.typeId() == "water"; + return it.typeId() == itype_water; } ); int charges_of_water = 0; for( const item *water : liquids ) { @@ -2139,7 +2212,7 @@ int iuse::water_purifier( player *p, item *it, bool, const tripoint & ) p->moves -= to_moves( 2_seconds ); for( item *water : liquids ) { - water->convert( "water_clean" ).poison = 0; + water->convert( itype_water_clean ).poison = 0; } return charges_of_water; } @@ -2150,7 +2223,7 @@ int iuse::radio_off( player *p, item *it, bool, const tripoint & ) p->add_msg_if_player( _( "It's dead." ) ); } else { p->add_msg_if_player( _( "You turn the radio on." ) ); - it->convert( "radio_on" ).active = true; + it->convert( itype_radio_on ).active = true; } return it->type->charges_to_use(); } @@ -2159,7 +2232,7 @@ int iuse::directional_antenna( player *p, item *it, bool, const tripoint & ) { // Find out if we have an active radio auto radios = p->items_with( []( const item & it ) { - return it.typeId() == "radio_on"; + return it.typeId() == itype_radio_on; } ); if( radios.empty() ) { add_msg( m_info, _( "Must have an active radio to check for signal direction." ) ); @@ -2257,7 +2330,7 @@ int iuse::radio_on( player *p, item *it, bool t, const tripoint &pos ) break; case 1: p->add_msg_if_player( _( "The radio dies." ) ); - it->convert( "radio" ).active = false; + it->convert( itype_radio ).active = false; sfx::fade_audio_channel( sfx::channel::radio, 300 ); break; default: @@ -2273,7 +2346,7 @@ int iuse::noise_emitter_off( player *p, item *it, bool, const tripoint & ) p->add_msg_if_player( _( "It's dead." ) ); } else { p->add_msg_if_player( _( "You turn the noise emitter on." ) ); - it->convert( "noise_emitter_on" ).active = true; + it->convert( itype_noise_emitter_on ).active = true; } return it->type->charges_to_use(); } @@ -2286,7 +2359,7 @@ int iuse::noise_emitter_on( player *p, item *it, bool t, const tripoint &pos ) "noise_emitter" ); } else { // Turning it off p->add_msg_if_player( _( "The infernal racket dies as the noise emitter turns off." ) ); - it->convert( "noise_emitter" ).active = false; + it->convert( itype_noise_emitter ).active = false; } return it->type->charges_to_use(); } @@ -2516,7 +2589,7 @@ int iuse::crowbar( player *p, item *it, bool, const tripoint &pos ) sounds::sound( pnt, 12, sounds::sound_t::combat, _( "crunch!" ), true, "tool", "crowbar" ); } if( type == t_manhole_cover ) { - g->m.spawn_item( pnt, "manhole_cover" ); + g->m.spawn_item( pnt, itype_manhole_cover ); } if( type == t_door_locked_alarm ) { g->events().send( p->getID() ); @@ -2538,9 +2611,9 @@ int iuse::crowbar( player *p, item *it, bool, const tripoint &pos ) p->add_msg_if_player( m_mixed, _( "You break the glass." ) ); sounds::sound( pnt, 24, sounds::sound_t::combat, _( "glass breaking!" ), true, "smash", "glass" ); g->m.ter_set( pnt, t_window_frame ); - g->m.spawn_item( pnt, "sheet", 2 ); - g->m.spawn_item( pnt, "stick" ); - g->m.spawn_item( pnt, "string_36" ); + g->m.spawn_item( pnt, itype_sheet, 2 ); + g->m.spawn_item( pnt, itype_stick ); + g->m.spawn_item( pnt, itype_string_36 ); return it->type->charges_to_use(); } } @@ -3040,7 +3113,7 @@ static int toolweapon_off( player &p, item &it, const bool fast_startup, { p.moves -= fast_startup ? 60 : 80; if( condition && it.units_sufficient( p ) ) { - if( it.typeId() == "chainsaw_off" ) { + if( it.typeId() == itype_chainsaw_off ) { sfx::play_variant_sound( "chainsaw_cord", "chainsaw_on", sfx::get_heard_volume( p.pos() ) ); sfx::play_variant_sound( "chainsaw_start", "chainsaw_on", sfx::get_heard_volume( p.pos() ) ); sfx::play_ambient_variant_sound( "chainsaw_idle", "chainsaw_on", sfx::get_heard_volume( p.pos() ), @@ -3050,11 +3123,12 @@ static int toolweapon_off( player &p, item &it, const bool fast_startup, 3000 ); } sounds::sound( p.pos(), volume, sounds::sound_t::combat, msg_success ); - it.convert( it.typeId().substr( 0, it.typeId().size() - 4 ) + "_on" ); // 4 is the length of "_off". + // 4 is the length of "_off". + it.convert( itype_id( it.typeId().str().substr( 0, it.typeId().str().size() - 4 ) + "_on" ) ); it.active = true; return it.type->charges_to_use(); } else { - if( it.typeId() == "chainsaw_off" ) { + if( it.typeId() == itype_chainsaw_off ) { sfx::play_variant_sound( "chainsaw_cord", "chainsaw_on", sfx::get_heard_volume( p.pos() ) ); } p.add_msg_if_player( msg_failure ); @@ -3140,7 +3214,7 @@ static int toolweapon_on( player &p, item &it, const bool t, const std::string &sound, const bool double_charge_cost = false ) { std::string off_type = - it.typeId().substr( 0, it.typeId().size() - 3 ) + + it.typeId().str().substr( 0, it.typeId().str().size() - 3 ) + // 3 is the length of "_on". "_off"; if( t ) { // Effects while simply on @@ -3149,18 +3223,18 @@ static int toolweapon_on( player &p, item &it, const bool t, } if( !works_underwater && p.is_underwater() ) { p.add_msg_if_player( _( "Your %s gurgles in the water and stops." ), tname ); - it.convert( off_type ).active = false; + it.convert( itype_id( off_type ) ).active = false; } else if( one_in( sound_chance ) ) { sounds::ambient_sound( p.pos(), volume, sounds::sound_t::activity, sound ); } } else { // Toggling - if( it.typeId() == "chainsaw_on" ) { + if( it.typeId() == itype_chainsaw_on ) { sfx::play_variant_sound( "chainsaw_stop", "chainsaw_on", sfx::get_heard_volume( p.pos() ) ); sfx::fade_audio_channel( sfx::channel::idle_chainsaw, 100 ); sfx::fade_audio_channel( sfx::channel::chainsaw_theme, 3000 ); } p.add_msg_if_player( _( "Your %s goes quiet." ), tname ); - it.convert( off_type ).active = false; + it.convert( itype_id( off_type ) ).active = false; return 0; // Don't consume charges when turning off. } return it.type->charges_to_use(); @@ -3428,9 +3502,9 @@ int iuse::geiger( player *p, item *it, bool t, const tripoint &pos ) return it->type->charges_to_use(); } // Otherwise, we're activating the geiger counter - if( it->typeId() == "geiger_on" ) { + if( it->typeId() == itype_geiger_on ) { add_msg( _( "The geiger counter's SCANNING LED turns off." ) ); - it->convert( "geiger_off" ).active = false; + it->convert( itype_geiger_off ).active = false; return 0; } @@ -3468,7 +3542,7 @@ int iuse::geiger( player *p, item *it, bool t, const tripoint &pos ) break; case 2: p->add_msg_if_player( _( "The geiger counter's scan LED turns on." ) ); - it->convert( "geiger_on" ).active = true; + it->convert( itype_geiger_on ).active = true; break; default: return 0; @@ -3498,7 +3572,7 @@ int iuse::teleport( player *p, item *it, bool, const tripoint & ) int iuse::can_goo( player *p, item *it, bool, const tripoint & ) { - it->convert( "canister_empty" ); + it->convert( itype_canister_empty ); int tries = 0; tripoint goop; goop.z = p->posz(); @@ -3574,7 +3648,7 @@ int iuse::throwable_extinguisher_act( player *, item *it, bool, const tripoint & int iuse::granade( player *p, item *it, bool, const tripoint & ) { p->add_msg_if_player( _( "You pull the pin on the Granade." ) ); - it->convert( "granade_act" ); + it->convert( itype_granade_act ); it->charges = 5; it->active = true; return it->type->charges_to_use(); @@ -3588,7 +3662,7 @@ int iuse::granade_act( player *p, item *it, bool t, const tripoint &pos ) if( t ) { // Simple timer effects // Vol 0 = only heard if you hold it sounds::sound( pos, 0, sounds::sound_t::electronic_speech, _( "Merged!" ), - true, "speech", it->typeId() ); + true, "speech", it->typeId().str() ); } else if( it->charges > 0 ) { p->add_msg_if_player( m_info, _( "You've already pulled the %s's pin, try throwing it instead." ), it->tname() ); @@ -3603,7 +3677,7 @@ int iuse::granade_act( player *p, item *it, bool t, const tripoint &pos ) switch( effect_roll ) { case 1: sounds::sound( pos, 100, sounds::sound_t::electronic_speech, _( "BUGFIXES!" ), - true, "speech", it->typeId() ); + true, "speech", it->typeId().str() ); explosion_handler::draw_explosion( pos, explosion_radius, c_light_cyan ); for( const tripoint &dest : g->m.points_in_radius( pos, explosion_radius ) ) { monster *const mon = g->critter_at( dest, true ); @@ -3615,7 +3689,7 @@ int iuse::granade_act( player *p, item *it, bool t, const tripoint &pos ) case 2: sounds::sound( pos, 100, sounds::sound_t::electronic_speech, _( "BUFFS!" ), - true, "speech", it->typeId() ); + true, "speech", it->typeId().str() ); explosion_handler::draw_explosion( pos, explosion_radius, c_green ); for( const tripoint &dest : g->m.points_in_radius( pos, explosion_radius ) ) { if( monster *const mon_ptr = g->critter_at( dest ) ) { @@ -3654,7 +3728,7 @@ int iuse::granade_act( player *p, item *it, bool t, const tripoint &pos ) case 3: sounds::sound( pos, 100, sounds::sound_t::electronic_speech, _( "NERFS!" ), - true, "speech", it->typeId() ); + true, "speech", it->typeId().str() ); explosion_handler::draw_explosion( pos, explosion_radius, c_red ); for( const tripoint &dest : g->m.points_in_radius( pos, explosion_radius ) ) { if( monster *const mon_ptr = g->critter_at( dest ) ) { @@ -3692,7 +3766,7 @@ int iuse::granade_act( player *p, item *it, bool t, const tripoint &pos ) case 4: sounds::sound( pos, 100, sounds::sound_t::electronic_speech, _( "REVERTS!" ), - true, "speech", it->typeId() ); + true, "speech", it->typeId().str() ); explosion_handler::draw_explosion( pos, explosion_radius, c_pink ); for( const tripoint &dest : g->m.points_in_radius( pos, explosion_radius ) ) { if( monster *const mon_ptr = g->critter_at( dest ) ) { @@ -3710,7 +3784,7 @@ int iuse::granade_act( player *p, item *it, bool t, const tripoint &pos ) break; case 5: sounds::sound( pos, 100, sounds::sound_t::electronic_speech, _( "BEES!" ), - true, "speech", it->typeId() ); + true, "speech", it->typeId().str() ); explosion_handler::draw_explosion( pos, explosion_radius, c_yellow ); for( const tripoint &dest : g->m.points_in_radius( pos, explosion_radius ) ) { if( one_in( 5 ) && !g->critter_at( dest ) ) { @@ -3732,7 +3806,7 @@ int iuse::c4( player *p, item *it, bool, const tripoint & ) return 0; } p->add_msg_if_player( _( "You set the timer to %d." ), time ); - it->convert( "c4armed" ); + it->convert( itype_c4armed ); it->charges = time; it->active = true; return it->type->charges_to_use(); @@ -3786,18 +3860,18 @@ int iuse::arrow_flammable( player *p, item *it, bool, const tripoint & ) p->add_msg_if_player( m_info, _( "You can't do that while underwater." ) ); return 0; } - if( !p->use_charges_if_avail( "fire", 1 ) ) { + if( !p->use_charges_if_avail( itype_fire, 1 ) ) { p->add_msg_if_player( m_info, _( "You need a source of fire!" ) ); return 0; } p->add_msg_if_player( _( "You light the arrow!" ) ); p->moves -= to_moves( 1_seconds ); if( it->charges == 1 ) { - it->convert( "arrow_flamming" ); + it->convert( itype_arrow_flamming ); return 0; } item lit_arrow( *it ); - lit_arrow.convert( "arrow_flamming" ).charges = 1; + lit_arrow.convert( itype_arrow_flamming ).charges = 1; p->i_add( lit_arrow ); return 1; } @@ -3814,7 +3888,7 @@ int iuse::molotov_lit( player *p, item *it, bool t, const tripoint &pos ) it->charges += 1; if( one_in( 5 ) ) { p->add_msg_if_player( _( "Your lit Molotov goes out." ) ); - it->convert( "molotov" ).active = false; + it->convert( itype_molotov ).active = false; } } else { if( !t ) { @@ -3833,12 +3907,12 @@ int iuse::firecracker_pack( player *p, item *it, bool, const tripoint & ) p->add_msg_if_player( m_info, _( "You can't do that while underwater." ) ); return 0; } - if( !p->has_charges( "fire", 1 ) ) { + if( !p->has_charges( itype_fire, 1 ) ) { p->add_msg_if_player( m_info, _( "You need a source of fire!" ) ); return 0; } p->add_msg_if_player( _( "You light the pack of firecrackers." ) ); - it->convert( "firecracker_pack_act" ); + it->convert( itype_firecracker_pack_act ); it->charges = 26; it->set_age( 0_turns ); it->active = true; @@ -3874,12 +3948,12 @@ int iuse::firecracker( player *p, item *it, bool, const tripoint & ) p->add_msg_if_player( m_info, _( "You can't do that while underwater." ) ); return 0; } - if( !p->use_charges_if_avail( "fire", 1 ) ) { + if( !p->use_charges_if_avail( itype_fire, 1 ) ) { p->add_msg_if_player( m_info, _( "You need a source of fire!" ) ); return 0; } p->add_msg_if_player( _( "You light the firecracker." ) ); - it->convert( "firecracker_act" ); + it->convert( itype_firecracker_act ); it->charges = 2; it->active = true; return it->type->charges_to_use(); @@ -3913,7 +3987,7 @@ int iuse::mininuke( player *p, item *it, bool, const tripoint & ) p->add_msg_if_player( _( "You set the timer to %s." ), to_string( time_duration::from_turns( time ) ) ); g->events().send( p->getID() ); - it->convert( "mininuke_act" ); + it->convert( itype_mininuke_act ); it->charges = time; it->active = true; return it->type->charges_to_use(); @@ -4078,7 +4152,7 @@ int iuse::shocktonfa_off( player *p, item *it, bool t, const tripoint &pos ) return 0; } else { p->add_msg_if_player( _( "You turn the light on." ) ); - it->convert( "shocktonfa_on" ).active = true; + it->convert( itype_shocktonfa_on ).active = true; return it->type->charges_to_use(); } } @@ -4093,7 +4167,7 @@ int iuse::shocktonfa_on( player *p, item *it, bool t, const tripoint &pos ) } else { if( !it->units_sufficient( *p ) ) { p->add_msg_if_player( m_info, _( "Your tactical tonfa is out of power." ) ); - it->convert( "shocktonfa_off" ).active = false; + it->convert( itype_shocktonfa_off ).active = false; } else { int choice = uilist( _( "tactical tonfa" ), { _( "Zap something" ), _( "Turn off light" ) @@ -4105,7 +4179,7 @@ int iuse::shocktonfa_on( player *p, item *it, bool t, const tripoint &pos ) } case 1: { p->add_msg_if_player( _( "You turn off the light." ) ); - it->convert( "shocktonfa_off" ).active = false; + it->convert( itype_shocktonfa_off ).active = false; } } } @@ -4118,20 +4192,20 @@ int iuse::mp3( player *p, item *it, bool, const tripoint & ) // TODO: avoid item id hardcoding to make this function usable for pure json-defined devices. if( !it->units_sufficient( *p ) ) { p->add_msg_if_player( m_info, _( "The device's batteries are dead." ) ); - } else if( p->has_active_item( "mp3_on" ) || p->has_active_item( "smartphone_music" ) || - p->has_active_item( "afs_atomic_smartphone_music" ) || - p->has_active_item( "afs_atomic_wraitheon_music" ) ) { + } else if( p->has_active_item( itype_mp3_on ) || p->has_active_item( itype_smartphone_music ) || + p->has_active_item( itype_afs_atomic_smartphone_music ) || + p->has_active_item( itype_afs_atomic_wraitheon_music ) ) { p->add_msg_if_player( m_info, _( "You are already listening to music!" ) ); } else { p->add_msg_if_player( m_info, _( "You put in the earbuds and start listening to music." ) ); - if( it->typeId() == "mp3" ) { - it->convert( "mp3_on" ).active = true; - } else if( it->typeId() == "smart_phone" ) { - it->convert( "smartphone_music" ).active = true; - } else if( it->typeId() == "afs_atomic_smartphone" ) { - it->convert( "afs_atomic_smartphone_music" ).active = true; - } else if( it->typeId() == "afs_wraitheon_smartphone" ) { - it->convert( "afs_atomic_wraitheon_music" ).active = true; + if( it->typeId() == itype_mp3 ) { + it->convert( itype_mp3_on ).active = true; + } else if( it->typeId() == itype_smart_phone ) { + it->convert( itype_smartphone_music ).active = true; + } else if( it->typeId() == itype_afs_atomic_smartphone ) { + it->convert( itype_afs_atomic_smartphone_music ).active = true; + } else if( it->typeId() == itype_afs_wraitheon_smartphone ) { + it->convert( itype_afs_atomic_wraitheon_music ).active = true; } p->mod_moves( -200 ); } @@ -4207,18 +4281,18 @@ int iuse::mp3_on( player *p, item *it, bool t, const tripoint &pos ) play_music( *p, pos, 0, 20 ); } } else { // Turning it off - if( it->typeId() == "mp3_on" ) { + if( it->typeId() == itype_mp3_on ) { p->add_msg_if_player( _( "The mp3 player turns off." ) ); - it->convert( "mp3" ).active = false; - } else if( it->typeId() == "smartphone_music" ) { + it->convert( itype_mp3 ).active = false; + } else if( it->typeId() == itype_smartphone_music ) { p->add_msg_if_player( _( "The phone turns off." ) ); - it->convert( "smart_phone" ).active = false; - } else if( it->typeId() == "afs_atomic_smartphone_music" ) { + it->convert( itype_smart_phone ).active = false; + } else if( it->typeId() == itype_afs_atomic_smartphone_music ) { p->add_msg_if_player( _( "The phone turns off." ) ); - it->convert( "afs_atomic_smartphone" ).active = false; - } else if( it->typeId() == "afs_atomic_wraitheon_music" ) { + it->convert( itype_afs_atomic_smartphone ).active = false; + } else if( it->typeId() == itype_afs_atomic_wraitheon_music ) { p->add_msg_if_player( _( "The phone turns off." ) ); - it->convert( "afs_wraitheon_smartphone" ).active = false; + it->convert( itype_afs_wraitheon_smartphone ).active = false; } p->mod_moves( -200 ); } @@ -4261,11 +4335,13 @@ int iuse::dive_tank( player *p, item *it, bool t, const tripoint & ) if( it->charges == 0 ) { p->add_msg_if_player( m_bad, _( "Air in your %s runs out." ), it->tname() ); it->set_var( "overwrite_env_resist", 0 ); - it->convert( it->typeId().substr( 0, it->typeId().size() - 3 ) ).active = false; // 3 = "_on" + it->convert( itype_id( it->typeId().str().substr( 0, + it->typeId().str().size() - 3 ) ) ).active = false; // 3 = "_on" } } else { // not worn = off thanks to on-demand regulator it->set_var( "overwrite_env_resist", 0 ); - it->convert( it->typeId().substr( 0, it->typeId().size() - 3 ) ).active = false; // 3 = "_on" + it->convert( itype_id( it->typeId().str().substr( 0, + it->typeId().str().size() - 3 ) ) ).active = false; // 3 = "_on" } } else { // Turning it on/off @@ -4274,20 +4350,22 @@ int iuse::dive_tank( player *p, item *it, bool t, const tripoint & ) } else if( it->active ) { //off p->add_msg_if_player( _( "You turn off the regulator and close the air valve." ) ); it->set_var( "overwrite_env_resist", 0 ); - it->convert( it->typeId().substr( 0, it->typeId().size() - 3 ) ).active = false; // 3 = "_on" + it->convert( itype_id( it->typeId().str().substr( 0, + it->typeId().str().size() - 3 ) ) ).active = false; // 3 = "_on" } else { //on if( !p->is_worn( *it ) ) { p->add_msg_if_player( _( "You should wear it first." ) ); } else { p->add_msg_if_player( _( "You turn on the regulator and open the air valve." ) ); it->set_var( "overwrite_env_resist", it->get_base_env_resist_w_filter() ); - it->convert( it->typeId() + "_on" ).active = true; + it->convert( itype_id( it->typeId().str() + "_on" ) ).active = true; } } } if( it->charges == 0 ) { it->set_var( "overwrite_env_resist", 0 ); - it->convert( it->typeId().substr( 0, it->typeId().size() - 3 ) ).active = false; // 3 = "_on" + it->convert( itype_id( it->typeId().str().substr( 0, + it->typeId().str().size() - 3 ) ) ).active = false; // 3 = "_on" } return it->type->charges_to_use(); } @@ -4317,7 +4395,7 @@ int iuse::solarpack( player *p, item *it, bool, const tripoint & ) p->add_msg_if_player( _( "You unfold solar array from the pack. You still need to connect it with a cable." ) ); - it->convert( it->typeId() + "_on" ); + it->convert( itype_id( it->typeId().str() + "_on" ) ); return 0; } @@ -4329,7 +4407,9 @@ int iuse::solarpack_off( player *p, item *it, bool, const tripoint & ) p->add_msg_if_player( _( "You unplug and fold your portable solar array into the pack." ) ); } - it->convert( it->typeId().substr( 0, it->typeId().size() - 3 ) ).active = false; // 3 = "_on" + // 3 = "_on" + it->convert( itype_id( it->typeId().str().substr( 0, + it->typeId().str().size() - 3 ) ) ).active = false; return 0; } @@ -4550,8 +4630,9 @@ int iuse::vibe( player *p, item *it, bool, const tripoint & ) return 0; } if( ( p->is_underwater() ) && ( !( ( p->has_trait( trait_GILLS ) ) || - ( p->is_wearing( "rebreather_on" ) ) || - ( p->is_wearing( "rebreather_xl_on" ) ) || ( p->is_wearing( "mask_h20survivor_on" ) ) ) ) ) { + ( p->is_wearing( itype_rebreather_on ) ) || + ( p->is_wearing( itype_rebreather_xl_on ) ) || + ( p->is_wearing( itype_mask_h20survivor_on ) ) ) ) ) { p->add_msg_if_player( m_info, _( "It's waterproof, but oxygen maybe?" ) ); return 0; } @@ -4595,14 +4676,14 @@ int iuse::vortex( player *p, item *it, bool, const tripoint & ) } p->add_msg_if_player( m_warning, _( "Air swirls all over…" ) ); p->moves -= to_moves( 1_seconds ); - it->convert( "spiral_stone" ); + it->convert( itype_spiral_stone ); mon->friendly = -1; return it->type->charges_to_use(); } // Only reachable when no monster has been spawned. p->add_msg_if_player( m_warning, _( "Air swirls around you for a moment." ) ); - return it->convert( "spiral_stone" ).type->charges_to_use(); + return it->convert( itype_spiral_stone ).type->charges_to_use(); } int iuse::dog_whistle( player *p, item *it, bool, const tripoint & ) @@ -4716,12 +4797,12 @@ int iuse::mind_splicer( player *p, item *it, bool, const tripoint & ) return 0; } for( auto &map_it : g->m.i_at( point( p->posx(), p->posy() ) ) ) { - if( map_it.typeId() == "rmi2_corpse" && + if( map_it.typeId() == itype_rmi2_corpse && query_yn( _( "Use the mind splicer kit on the %s?" ), colorize( map_it.tname(), map_it.color_in_inventory() ) ) ) { auto filter = []( const item & it ) { - return it.typeId() == "data_card"; + return it.typeId() == itype_data_card; }; avatar *you = p->as_avatar(); item_location loc; @@ -4772,7 +4853,7 @@ int iuse::lumber( player *p, item *it, bool t, const tripoint & ) } // Check if player is standing on any lumber for( auto &i : g->m.i_at( p->pos() ) ) { - if( i.typeId() == "log" ) { + if( i.typeId() == itype_log ) { g->m.i_rem( p->pos(), &i ); cut_log_into_planks( *p ); return it->type->charges_to_use(); @@ -4783,7 +4864,7 @@ int iuse::lumber( player *p, item *it, bool t, const tripoint & ) avatar *you = p->as_avatar(); item_location loc; auto filter = []( const item & it ) { - return it.typeId() == "log"; + return it.typeId() == itype_log; }; if( you != nullptr ) { loc = game_menus::inv::titled_filter_menu( filter, *you, _( "Cut up what?" ) ); @@ -5636,7 +5717,7 @@ static bool heat_item( player &p ) int iuse::heatpack( player *p, item *it, bool, const tripoint & ) { if( heat_item( *p ) ) { - it->convert( "heatpack_used" ); + it->convert( itype_heatpack_used ); } return 0; } @@ -5663,7 +5744,7 @@ int iuse::hotplate( player *p, item *it, bool, const tripoint & ) p->add_msg_if_player( m_info, _( "You cannot do that while mounted." ) ); return 0; } - if( it->typeId() != "atomic_coffeepot" && ( !it->units_sufficient( *p ) ) ) { + if( it->typeId() != itype_atomic_coffeepot && ( !it->units_sufficient( *p ) ) ) { p->add_msg_if_player( m_info, _( "The %s's batteries are dead." ), it->tname() ); return 0; } @@ -5720,8 +5801,8 @@ int iuse::towel_common( player *p, item *it, bool t ) name ); towelUsed = true; - if( it && it->typeId() == "towel" ) { - it->convert( "towel_soiled" ); + if( it && it->typeId() == itype_towel ) { + it->convert( itype_towel_soiled ); } // dry off from being wet @@ -5749,8 +5830,8 @@ int iuse::towel_common( player *p, item *it, bool t ) p->moves -= 50 * mult; if( it ) { // change "towel" to a "towel_wet" (different flavor text/color) - if( it->typeId() == "towel" ) { - it->convert( "towel_wet" ); + if( it->typeId() == itype_towel ) { + it->convert( itype_towel_wet ); } // WET, active items have their timer decremented every turn @@ -5947,10 +6028,10 @@ int iuse::talking_doll( player *p, item *it, bool, const tripoint & ) return 0; } - const SpeechBubble speech = get_speech( it->typeId() ); + const SpeechBubble speech = get_speech( it->typeId().str() ); sounds::sound( p->pos(), speech.volume, sounds::sound_t::electronic_speech, - speech.text.translated(), true, "speech", it->typeId() ); + speech.text.translated(), true, "speech", it->typeId().str() ); // Sound code doesn't describe noises at the player position if( p->can_hear( p->pos(), speech.volume ) ) { @@ -6070,8 +6151,9 @@ int iuse::toolmod_attach( player *p, item *it, bool, const tripoint & ) auto filter = [&it]( const item & e ) { // don't allow ups battery mods on a UPS or UPS-powered tools - if( it->has_flag( "USE_UPS" ) && ( e.typeId() == "UPS_off" || e.typeId() == "adv_UPS_off" || - e.has_flag( "USE_UPS" ) ) ) { + if( it->has_flag( "USE_UPS" ) && + ( e.typeId() == itype_UPS_off || e.typeId() == itype_adv_UPS_off || + e.has_flag( "USE_UPS" ) ) ) { return false; } @@ -6104,7 +6186,7 @@ int iuse::toolmod_attach( player *p, item *it, bool, const tripoint & ) int iuse::bell( player *p, item *it, bool, const tripoint & ) { - if( it->typeId() == "cow_bell" ) { + if( it->typeId() == itype_cow_bell ) { sounds::sound( p->pos(), 12, sounds::sound_t::music, _( "Clank! Clank!" ), true, "misc", "cow_bell" ); if( !p->is_deaf() ) { @@ -6262,7 +6344,7 @@ static void init_memory_card_with_random_stuff( item &it ) bool encrypted = false; if( it.has_flag( "MC_MAY_BE_ENCRYPTED" ) && one_in( 8 ) ) { - it.convert( it.typeId() + "_encrypted" ); + it.convert( itype_id( it.typeId().str() + "_encrypted" ) ); } //some special cards can contain "MC_ENCRYPTED" flag @@ -6469,7 +6551,7 @@ static bool einkpc_download_memory_card( player &p, item &eink, item &mc ) if( mc.has_flag( "MC_TURN_USED" ) ) { mc.clear_vars(); mc.unset_flags(); - mc.convert( "mobile_memory_card_used" ); + mc.convert( itype_mobile_memory_card_used ); } if( !something_downloaded ) { @@ -6814,7 +6896,7 @@ int iuse::einktabletpc( player *p, item *it, bool t, const tripoint &pos ) _( "You tripped the firmware protection, and the card deleted its data!" ) ); mc.clear_vars(); mc.unset_flags(); - mc.convert( "mobile_memory_card_used" ); + mc.convert( itype_mobile_memory_card_used ); } } return it->type->charges_to_use(); @@ -7881,7 +7963,7 @@ int iuse::camera( player *p, item *it, bool, const tripoint & ) } } - mc.convert( "mobile_memory_card" ); + mc.convert( itype_mobile_memory_card ); mc.clear_vars(); mc.unset_flags(); mc.item_tags.insert( "MC_HAS_DATA" ); @@ -7916,7 +7998,7 @@ int iuse::ehandcuffs( player *p, item *it, bool t, const tripoint &pos ) it->item_tags.erase( "NO_UNWIELD" ); it->active = false; - if( p->has_item( *it ) && p->weapon.typeId() == "e_handcuffs" ) { + if( p->has_item( *it ) && p->weapon.typeId() == itype_e_handcuffs ) { add_msg( m_good, _( "%s on your hands opened!" ), it->tname() ); } @@ -7949,7 +8031,7 @@ int iuse::ehandcuffs( player *p, item *it, bool t, const tripoint &pos ) if( ( it->ammo_remaining() > it->type->maximum_charges() - 1000 ) && ( x != pos.x || y != pos.y ) ) { - if( p->has_item( *it ) && p->weapon.typeId() == "e_handcuffs" ) { + if( p->has_item( *it ) && p->weapon.typeId() == itype_e_handcuffs ) { if( p->is_elec_immune() ) { if( one_in( 10 ) ) { @@ -8038,7 +8120,7 @@ int iuse::radiocar( player *p, item *it, bool, const tripoint & ) return 0; } - it->convert( "radio_car_on" ).active = true; + it->convert( itype_radio_car_on ).active = true; p->add_msg_if_player( _( "You turned on your RC car, now place it on ground, and use radio control to play." ) ); @@ -8112,7 +8194,7 @@ int iuse::radiocaron( player *p, item *it, bool t, const tripoint &pos ) } if( choice == 0 ) { - it->convert( "radio_car" ).active = false; + it->convert( itype_radio_car ).active = false; p->add_msg_if_player( _( "You turned off your RC car." ) ); return it->type->charges_to_use(); @@ -8192,7 +8274,7 @@ int iuse::radiocontrol( player *p, item *it, bool t, const tripoint & ) tripoint rc_item_location = {999, 999, 999}; // TODO: grab the closest car or similar? for( auto &rc_pairs_rc_pair : rc_pairs ) { - if( rc_pairs_rc_pair.second->typeId() == "radio_car_on" && + if( rc_pairs_rc_pair.second->typeId() == itype_radio_car_on && rc_pairs_rc_pair.second->active ) { rc_item_location = rc_pairs_rc_pair.first; } @@ -8318,7 +8400,7 @@ static vehicle *pickveh( const tripoint ¢er, bool advanced ) for( auto &veh : g->m.get_vehicles() ) { auto &v = veh.v; if( rl_dist( center, v->global_pos3() ) < 40 && - v->fuel_left( "battery", true ) > 0 && + v->fuel_left( itype_battery, true ) > 0 && ( !empty( v->get_avail_parts( advctrl ) ) || ( !advanced && !empty( v->get_avail_parts( ctrl ) ) ) ) ) { vehs.push_back( v ); @@ -8359,7 +8441,7 @@ int iuse::remoteveh( player *p, item *it, bool t, const tripoint &pos ) } else if( remote == nullptr ) { p->add_msg_if_player( _( "Lost contact with the vehicle." ) ); stop = true; - } else if( remote->fuel_left( "battery", true ) == 0 ) { + } else if( remote->fuel_left( itype_battery, true ) == 0 ) { p->add_msg_if_player( m_bad, _( "The vehicle's battery died." ) ); stop = true; } @@ -8724,7 +8806,7 @@ int iuse::multicooker( player *p, item *it, bool t, const tripoint &pos ) it->remove_item( *dish_it ); it->erase_var( "RECIPE" ); - it->convert( "multi_cooker" ); + it->convert( itype_multi_cooker ); if( is_delicious ) { p->add_msg_if_player( m_good, _( "You got the dish from the multi-cooker. The %s smells delicious." ), @@ -8800,13 +8882,13 @@ int iuse::multicooker( player *p, item *it, bool t, const tripoint &pos ) } it->set_var( "RECIPE", meal->ident().str() ); - it->set_var( "DISH", meal->result() ); + it->set_var( "DISH", meal->result().str() ); it->set_var( "COOKTIME", mealtime ); p->add_msg_if_player( m_good, _( "The screen flashes blue symbols and scales as the multi-cooker begins to shake." ) ); - it->convert( "multi_cooker_filled" ).active = true; + it->convert( itype_multi_cooker_filled ).active = true; it->ammo_consume( charges_to_start, pos ); p->practice( skill_cooking, meal->difficulty * 3 ); //little bonus @@ -8826,8 +8908,9 @@ int iuse::multicooker( player *p, item *it, bool t, const tripoint &pos ) const inventory &cinv = g->u.crafting_inventory(); - if( !cinv.has_amount( "soldering_iron", 1 ) ) { - p->add_msg_if_player( m_warning, _( "You need a %s." ), item::nname( "soldering_iron" ) ); + if( !cinv.has_amount( itype_soldering_iron, 1 ) ) { + p->add_msg_if_player( m_warning, _( "You need a %s." ), + item::nname( itype_soldering_iron ) ); has_tools = false; } @@ -8994,7 +9077,7 @@ int iuse::tow_attach( player *p, item *it, bool, const tripoint & ) p->add_msg_if_player( _( "You can't attach the tow-line to an internal part." ) ); return 0; } - const vpart_id vpid( it->typeId() ); + const vpart_id vpid( it->typeId().str() ); point vcoords = source_vp->mount(); vehicle_part source_part( vpid, vcoords, item( *it ) ); source_veh->install_part( vcoords, source_part ); @@ -9021,7 +9104,7 @@ int iuse::cable_attach( player *p, item *it, bool, const tripoint & ) const bool has_solar_pack = p->worn_with_flag( "SOLARPACK" ); const bool has_solar_pack_on = p->worn_with_flag( "SOLARPACK_ON" ); const bool wearing_solar_pack = has_solar_pack || has_solar_pack_on; - const bool has_ups = p->has_charges( "UPS_off", 1 ) || p->has_charges( "adv_UPS_off", 1 ); + const bool has_ups = p->has_charges( itype_UPS_off, 1 ) || p->has_charges( itype_adv_UPS_off, 1 ); item_location loc; avatar *you = p->as_avatar(); @@ -9228,7 +9311,7 @@ int iuse::cable_attach( player *p, item *it, bool, const tripoint & ) tripoint target_global = g->m.getabs( vpos ); // TODO: make sure there is always a matching vpart id here. Maybe transform this into // a iuse_actor class, or add a check in item_factory. - const vpart_id vpid( it->typeId() ); + const vpart_id vpid( it->typeId().str() ); point vcoords = source_vp->mount(); vehicle_part source_part( vpid, vcoords, item( *it ) ); @@ -9290,12 +9373,12 @@ int iuse::weather_tool( player *p, item *it, bool, const tripoint & ) /* Possibly used twice. Worth spending the time to precalculate. */ const auto player_local_temp = g->weather.get_temperature( g->u.pos() ); - if( it->typeId() == "weather_reader" ) { + if( it->typeId() == itype_weather_reader ) { p->add_msg_if_player( m_neutral, _( "The %s's monitor slowly outputs the data…" ), it->tname() ); } if( it->has_flag( "THERMOMETER" ) ) { - if( it->typeId() == "thermometer" ) { + if( it->typeId() == itype_thermometer ) { p->add_msg_if_player( m_neutral, _( "The %1$s reads %2$s." ), it->tname(), print_temperature( player_local_temp ) ); } else { @@ -9304,7 +9387,7 @@ int iuse::weather_tool( player *p, item *it, bool, const tripoint & ) } } if( it->has_flag( "HYGROMETER" ) ) { - if( it->typeId() == "hygrometer" ) { + if( it->typeId() == itype_hygrometer ) { p->add_msg_if_player( m_neutral, _( "The %1$s reads %2$s." ), it->tname(), print_humidity( get_local_humidity( weatherPoint.humidity, g->weather.weather, @@ -9317,7 +9400,7 @@ int iuse::weather_tool( player *p, item *it, bool, const tripoint & ) } } if( it->has_flag( "BAROMETER" ) ) { - if( it->typeId() == "barometer" ) { + if( it->typeId() == itype_barometer ) { p->add_msg_if_player( m_neutral, _( "The %1$s reads %2$s." ), it->tname(), print_pressure( static_cast( weatherPoint.pressure ) ) ); @@ -9327,7 +9410,7 @@ int iuse::weather_tool( player *p, item *it, bool, const tripoint & ) } } - if( it->typeId() == "weather_reader" ) { + if( it->typeId() == itype_weather_reader ) { int vehwindspeed = 0; if( optional_vpart_position vp = g->m.veh_at( p->pos() ) ) { vehwindspeed = std::abs( vp->vehicle().velocity / 100 ); // For mph @@ -9633,11 +9716,11 @@ int iuse::wash_items( player *p, bool soft_items, bool hard_items ) return it.made_of( LIQUID ); }; int available_water = std::max( - crafting_inv.charges_of( "water", INT_MAX, is_liquid ), - crafting_inv.charges_of( "water_clean", INT_MAX, is_liquid ) + crafting_inv.charges_of( itype_water, INT_MAX, is_liquid ), + crafting_inv.charges_of( itype_water_clean, INT_MAX, is_liquid ) ); - int available_cleanser = std::max( crafting_inv.charges_of( "soap" ), - crafting_inv.charges_of( "detergent" ) ); + int available_cleanser = std::max( crafting_inv.charges_of( itype_soap ), + crafting_inv.charges_of( itype_detergent ) ); const inventory_filter_preset preset( [soft_items, hard_items]( const item_location & location ) { return location->has_flag( "FILTHY" ) && ( ( soft_items && location->is_soft() ) || @@ -9692,13 +9775,13 @@ int iuse::wash_items( player *p, bool soft_items, bool hard_items ) washing_requirements required = washing_requirements_for_volume( total_volume ); - if( !crafting_inv.has_charges( "water", required.water, is_liquid ) && - !crafting_inv.has_charges( "water_clean", required.water, is_liquid ) ) { + if( !crafting_inv.has_charges( itype_water, required.water, is_liquid ) && + !crafting_inv.has_charges( itype_water_clean, required.water, is_liquid ) ) { p->add_msg_if_player( _( "You need %1$i charges of water or clean water to wash these items." ), required.water ); return 0; - } else if( !crafting_inv.has_charges( "soap", required.cleanser ) && - !crafting_inv.has_charges( "detergent", required.cleanser ) ) { + } else if( !crafting_inv.has_charges( itype_soap, required.cleanser ) && + !crafting_inv.has_charges( itype_detergent, required.cleanser ) ) { p->add_msg_if_player( _( "You need %1$i charges of cleansing agent to wash these items." ), required.cleanser ); return 0; diff --git a/src/iuse.h b/src/iuse.h index 14d2f255a2879..e244ad758cb4d 100644 --- a/src/iuse.h +++ b/src/iuse.h @@ -8,6 +8,7 @@ #include #include "clone_ptr.h" +#include "type_id.h" #include "units.h" class Character; @@ -17,8 +18,6 @@ class monster; class player; struct iteminfo; template class ret_val; - -using itype_id = std::string; struct tripoint; // iuse methods returning a bool indicating whether to consume a charge of the item being used. diff --git a/src/iuse_actor.cpp b/src/iuse_actor.cpp index 595f053cbe0da..98ab329ddeccd 100644 --- a/src/iuse_actor.cpp +++ b/src/iuse_actor.cpp @@ -109,6 +109,13 @@ static const fault_id fault_bionic_salvaged( "fault_bionic_salvaged" ); static const bionic_id bio_syringe( "bio_syringe" ); +static const itype_id itype_barrel_small( "barrel_small" ); +static const itype_id itype_brazier( "brazier" ); +static const itype_id itype_char_smoker( "char_smoker" ); +static const itype_id itype_fire( "fire" ); +static const itype_id itype_syringe( "syringe" ); +static const itype_id itype_UPS( "UPS" ); + static const skill_id skill_fabrication( "fabrication" ); static const skill_id skill_firstaid( "firstaid" ); static const skill_id skill_lockpick( "lockpick" ); @@ -150,7 +157,7 @@ std::unique_ptr iuse_transform::clone() const void iuse_transform::load( const JsonObject &obj ) { - target = obj.get_string( "target" ); // required + obj.read( "target", target, true ); obj.read( "msg", msg_transform ); obj.read( "container", container ); @@ -171,7 +178,7 @@ void iuse_transform::load( const JsonObject &obj ) obj.read( "countdown", countdown ); - if( !ammo_type.empty() && !container.empty() ) { + if( !ammo_type.is_empty() && !container.is_empty() ) { obj.throw_error( "Transform actor specified both ammo type and container type", "target_ammo" ); } @@ -227,7 +234,7 @@ int iuse_transform::use( player &p, item &it, bool t, const tripoint &pos ) cons } if( need_fire && possess ) { - if( !p.use_charges_if_avail( "fire", need_fire ) ) { + if( !p.use_charges_if_avail( itype_fire, need_fire ) ) { p.add_msg_if_player( m_info, need_fire_msg, it.tname() ); return 0; } @@ -249,7 +256,7 @@ int iuse_transform::use( player &p, item &it, bool t, const tripoint &pos ) cons item *obj; // defined here to allow making a new item assigned to the pointer item obj_it; - if( container.empty() ) { + if( container.is_empty() ) { obj = &it.convert( target ); if( ammo_qty >= 0 || !random_ammo_qty.empty() ) { int qty; @@ -259,9 +266,9 @@ int iuse_transform::use( player &p, item &it, bool t, const tripoint &pos ) cons } else { qty = ammo_qty; } - if( !ammo_type.empty() ) { + if( !ammo_type.is_empty() ) { obj->ammo_set( ammo_type, qty ); - } else if( obj->ammo_current() != "null" ) { + } else if( !obj->ammo_current().is_null() ) { obj->ammo_set( obj->ammo_current(), qty ); } else { obj->set_countdown( qty ); @@ -321,7 +328,7 @@ void iuse_transform::finalize( const itype_id & ) debugmsg( "Invalid transform target: %s", target.c_str() ); } - if( !container.empty() ) { + if( !container.is_empty() ) { if( !item::type_is_defined( container ) ) { debugmsg( "Invalid transform container: %s", container.c_str() ); } @@ -630,7 +637,7 @@ int unfold_vehicle_iuse::use( player &p, item &it, bool, const tripoint & ) cons // Mark the vehicle as foldable. veh->tags.insert( "convertible" ); // Store the id of the item the vehicle is made of. - veh->tags.insert( std::string( "convertible:" ) + it.typeId() ); + veh->tags.insert( std::string( "convertible:" ) + it.typeId().str() ); if( !unfold_msg.empty() ) { p.add_msg_if_player( _( unfold_msg ), it.tname() ); } @@ -737,7 +744,7 @@ void consume_drug_iuse::info( const item &, std::vector &dump ) const dump.emplace_back( "TOOL", _( "Vitamins (RDA): " ), vits ); } - if( tools_needed.count( "syringe" ) ) { + if( tools_needed.count( itype_syringe ) ) { dump.emplace_back( "TOOL", _( "You need a syringe to inject this drug." ) ); } } @@ -745,8 +752,8 @@ void consume_drug_iuse::info( const item &, std::vector &dump ) const int consume_drug_iuse::use( player &p, item &it, bool, const tripoint & ) const { auto need_these = tools_needed; - if( need_these.count( "syringe" ) && p.has_bionic( bio_syringe ) ) { - need_these.erase( "syringe" ); // no need for a syringe with bionics like these! + if( need_these.count( itype_syringe ) && p.has_bionic( bio_syringe ) ) { + need_these.erase( itype_syringe ); // no need for a syringe with bionics like these! } // Check prerequisites first. for( const auto &tool : need_these ) { @@ -999,7 +1006,7 @@ static bool has_powersource( const item &i, const player &p ) if( i.is_power_armor() && p.can_interface_armor() && p.has_power() ) { return true; } - return p.has_charges( "UPS", 1 ); + return p.has_charges( itype_UPS, 1 ); } int ups_based_armor_actor::use( player &p, item &it, bool t, const tripoint & ) const @@ -1134,7 +1141,7 @@ void deploy_furn_actor::info( const item &, std::vector &dump ) const if( the_furn.has_flag( "FIRE_CONTAINER" ) ) { can_function_as.emplace_back( _( "a safe place to contain a fire" ) ); } - if( the_furn.crafting_pseudo_item == "char_smoker" ) { + if( the_furn.crafting_pseudo_item == itype_char_smoker ) { can_function_as.emplace_back( _( "a place to smoke or dry food for preservation" ) ); } @@ -1301,7 +1308,7 @@ bool firestarter_actor::prep_firestarter_use( const player &p, tripoint &pos ) // Check for a brazier. bool has_unactivated_brazier = false; for( const auto &i : g->m.i_at( pos ) ) { - if( i.typeId() == "brazier" ) { + if( i.typeId() == itype_brazier ) { has_unactivated_brazier = true; } } @@ -1548,7 +1555,7 @@ int salvage_actor::cut_up( player &p, item &it, item_location &cut ) const // What material components can we get back? std::vector cut_material_components = cut.get_item()->made_of(); // What materials do we salvage (ids and counts). - std::map materials_salvaged; + std::map materials_salvaged; // Final just in case check (that perhaps was not done elsewhere); if( cut.get_item() == &it ) { @@ -1610,7 +1617,7 @@ int salvage_actor::cut_up( player &p, item &it, item_location &cut ) const p.reset_encumbrance(); for( const auto &salvaged : materials_salvaged ) { - std::string mat_name = salvaged.first; + itype_id mat_name = salvaged.first; int amount = salvaged.second; item result( mat_name, calendar::turn ); if( amount > 0 ) { @@ -1724,7 +1731,7 @@ bool inscribe_actor::item_inscription( item &tool, item &cut ) const cut.erase_var( carving_tool ); } else { cut.set_var( carving, message ); - cut.set_var( carving_tool, tool.typeId() ); + cut.set_var( carving_tool, tool.typeId().str() ); } return true; @@ -1858,7 +1865,7 @@ int cauterize_actor::use( player &p, item &it, bool t, const tripoint & ) const } if( flame ) { - p.use_charges( "fire", 4 ); + p.use_charges( itype_fire, 4 ); return 0; } else { @@ -1883,7 +1890,7 @@ ret_val cauterize_actor::can_use( const Character &p, const item &it, bool } if( flame ) { - if( !p.has_charges( "fire", 4 ) ) { + if( !p.has_charges( itype_fire, 4 ) ) { return ret_val::make_failure( _( "You need a source of flame (4 charges worth) before you can cauterize yourself." ) ); } @@ -1903,7 +1910,7 @@ ret_val cauterize_actor::can_use( const Character &p, const item &it, bool void fireweapon_off_actor::load( const JsonObject &obj ) { - target_id = obj.get_string( "target_id" ); + obj.read( "target_id", target_id, true ); success_message = obj.get_string( "success_message", "hsss" ); lacks_fuel_message = obj.get_string( "lacks_fuel_message" ); failure_message = obj.get_string( "failure_message", "hsss" ); @@ -2165,10 +2172,10 @@ int musical_instrument_actor::use( player &p, item &it, bool t, const tripoint & if( morale_effect >= 0 ) { sounds::sound( p.pos(), volume, sounds::sound_t::music, desc, true, "musical_instrument", - it.typeId() ); + it.typeId().str() ); } else { sounds::sound( p.pos(), volume, sounds::sound_t::music, desc, true, "musical_instrument_bad", - it.typeId() ); + it.typeId().str() ); } if( !p.has_effect( effect_music ) && p.can_hear( p.pos(), volume ) ) { @@ -2495,7 +2502,7 @@ std::unique_ptr ammobelt_actor::clone() const void ammobelt_actor::load( const JsonObject &obj ) { - belt = obj.get_string( "belt" ); + belt = itype_id( obj.get_string( "belt" ) ); } void ammobelt_actor::info( const item &, std::vector &dump ) const @@ -2760,7 +2767,7 @@ int repair_item_actor::repair_recipe_difficulty( const player &pl, int diff = find_repair_difficulty( pl, fix.typeId(), training ); // If we don't find a recipe, see if there's a repairs_like that has a recipe - if( diff == -1 && !fix.type->repairs_like.empty() ) { + if( diff == -1 && !fix.type->repairs_like.is_empty() ) { diff = find_repair_difficulty( pl, fix.type->repairs_like, training ); } @@ -3143,10 +3150,10 @@ void heal_actor::load( const JsonObject &obj ) } if( obj.has_string( "used_up_item" ) ) { - used_up_item_id = obj.get_string( "used_up_item", used_up_item_id ); + obj.read( "used_up_item", used_up_item_id, true ); } else if( obj.has_object( "used_up_item" ) ) { JsonObject u = obj.get_object( "used_up_item" ); - used_up_item_id = u.get_string( "id", used_up_item_id ); + u.read( "id", used_up_item_id, true ); used_up_item_quantity = u.get_int( "quantity", used_up_item_quantity ); used_up_item_charges = u.get_int( "charges", used_up_item_charges ); used_up_item_flags = u.get_tags( "flags" ); @@ -3334,7 +3341,7 @@ int heal_actor::finish_using( player &healer, player &patient, item &it, hp_part patient.add_effect( eff.id, eff.duration, eff.bp, eff.permanent ); } - if( !used_up_item_id.empty() ) { + if( !used_up_item_id.is_empty() ) { // If the item is a tool, `make` it the new form // Otherwise it probably was consumed, so create a new one if( it.is_tool() ) { @@ -3790,7 +3797,7 @@ ret_val saw_barrel_actor::can_use_on( const player &, const item &, const return ret_val::make_failure( _( "The barrel is too short." ) ); } - if( target.gunmod_find( "barrel_small" ) ) { + if( target.gunmod_find( itype_barrel_small ) ) { return ret_val::make_failure( _( "The barrel is already sawn-off." ) ); } diff --git a/src/iuse_actor.h b/src/iuse_actor.h index b2f5c7ebaf521..8574eb43824c7 100644 --- a/src/iuse_actor.h +++ b/src/iuse_actor.h @@ -33,8 +33,6 @@ struct tripoint; enum hp_part : int; enum body_part : int; class JsonObject; - -using itype_id = std::string; class item_location; struct furn_t; struct itype; @@ -56,10 +54,10 @@ class iuse_transform : public iuse_actor translation msg_transform; /** type of the resulting item */ - std::string target; + itype_id target; /** if set transform item to container and place new item (of type @ref target) inside */ - std::string container; + itype_id container; /** if zero or positive set remaining ammo of @ref target to this (after transformation) */ int ammo_qty = -1; @@ -71,7 +69,7 @@ class iuse_transform : public iuse_actor int countdown = 0; /** if both this and ammo_qty are specified then set @ref target to this specific ammo */ - std::string ammo_type; + itype_id ammo_type; /** used to set the active property of the transformed @ref target */ bool active = false; @@ -218,7 +216,7 @@ class unfold_vehicle_iuse : public iuse_actor std::string unfold_msg; /** Creature::moves it takes to unfold. */ int moves = 0; - std::map tools_needed; + std::map tools_needed; unfold_vehicle_iuse( const std::string &type = "unfold_vehicle" ) : iuse_actor( type ) {} @@ -250,9 +248,9 @@ class consume_drug_iuse : public iuse_actor /** Fields to produce when you take the drug, mostly intended for various kinds of smoke. **/ std::map fields_produced; /** Tool charges needed to take the drug, e.g. fire. **/ - std::map charges_needed; + std::map charges_needed; /** Tools needed, but not consumed, e.g. "smoking apparatus". **/ - std::map tools_needed; + std::map tools_needed; /** An effect or effects (conditions) to give the player for the stated duration. **/ std::vector effects; /** A list of stats and adjustments to them. **/ @@ -630,7 +628,7 @@ class cauterize_actor : public iuse_actor class fireweapon_off_actor : public iuse_actor { public: - std::string target_id; + itype_id target_id; std::string success_message; std::string lacks_fuel_message; std::string failure_message; // Due to bad roll @@ -938,7 +936,7 @@ class heal_actor : public iuse_actor * If the used item is a tool it, it will be turned into the used up item. * If it is not a tool a new item with this id will be created. */ - std::string used_up_item_id; + itype_id used_up_item_id; int used_up_item_quantity = 1; int used_up_item_charges = 1; std::set used_up_item_flags; diff --git a/src/json.h b/src/json.h index 61844e9593b4f..cf3f4ad88429a 100644 --- a/src/json.h +++ b/src/json.h @@ -1087,10 +1087,10 @@ class JsonArray return jsin->read( t ); } // random-access read values by reference - template bool read( size_t i, T &t ) const { + template bool read( size_t i, T &t, bool throw_on_error = false ) const { verify_index( i ); jsin->seek( positions[i] ); - return jsin->read( t ); + return jsin->read( t, throw_on_error ); } }; @@ -1124,8 +1124,8 @@ class JsonValue return seek().get_array(); } template - bool read( T &t ) const { - return seek().read( t ); + bool read( T &t, bool throw_on_error = false ) const { + return seek().read( t, throw_on_error ); } bool test_string() const { diff --git a/src/magic.cpp b/src/magic.cpp index e34d5d8ac04b0..bcf2cbd13f587 100644 --- a/src/magic.cpp +++ b/src/magic.cpp @@ -1764,8 +1764,8 @@ void spellcasting_callback::draw_spell_info( const spell &sp, const uilist *menu aoe_string = string_format( "%s: %d", _( "Variance" ), sp.aoe() ); } } else if( fx == "spawn_item" ) { - damage_string = string_format( "%s %d %s", _( "Spawn" ), sp.damage(), item::nname( sp.effect_data(), - sp.damage() ) ); + damage_string = string_format( "%s %d %s", _( "Spawn" ), sp.damage(), + item::nname( itype_id( sp.effect_data() ), sp.damage() ) ); } else if( fx == "summon" ) { std::string monster_name = "FIXME"; if( sp.has_flag( spell_flag::SPAWN_GROUP ) ) { diff --git a/src/map.cpp b/src/map.cpp index 2a4db3e9e076a..e91a8a50d5593 100755 --- a/src/map.cpp +++ b/src/map.cpp @@ -92,6 +92,24 @@ #include "weather.h" #include "weighted_list.h" +static const itype_id itype_battery( "battery" ); +static const itype_id itype_chemistry_set( "chemistry_set" ); +static const itype_id itype_dehydrator( "dehydrator" ); +static const itype_id itype_electrolysis_kit( "electrolysis_kit" ); +static const itype_id itype_food_processor( "food_processor" ); +static const itype_id itype_forge( "forge" ); +static const itype_id itype_glass_shard( "glass_shard" ); +static const itype_id itype_hotplate( "hotplate" ); +static const itype_id itype_kiln( "kiln" ); +static const itype_id itype_nail( "nail" ); +static const itype_id itype_press( "press" ); +static const itype_id itype_sheet( "sheet" ); +static const itype_id itype_soldering_iron( "soldering_iron" ); +static const itype_id itype_stick( "stick" ); +static const itype_id itype_string_36( "string_36" ); +static const itype_id itype_vac_sealer( "vac_sealer" ); +static const itype_id itype_welder( "welder" ); + static const mtype_id mon_zombie( "mon_zombie" ); static const skill_id skill_traps( "traps" ); @@ -2401,7 +2419,7 @@ void map::make_rubble( const tripoint &p, const furn_id &rubble_type, const bool for( int i = 0; i < splinter_count; i++ ) { add_item_or_charges( p, splinter ); } - spawn_item( p, "nail", 1, rng( 20, 50 ) ); + spawn_item( p, itype_nail, 1, rng( 20, 50 ) ); } } @@ -3501,9 +3519,9 @@ void map::shoot( const tripoint &p, projectile &proj, const bool hit_items ) if( dam > 0 ) { break_glass( p, 16 ); ter_set( p, t_window_frame ); - spawn_item( p, "sheet", 1 ); - spawn_item( p, "stick" ); - spawn_item( p, "string_36" ); + spawn_item( p, itype_sheet, 1 ); + spawn_item( p, itype_stick ); + spawn_item( p, itype_string_36 ); } } } else if( terrain == t_window_taped || @@ -3531,7 +3549,7 @@ void map::shoot( const tripoint &p, projectile &proj, const bool hit_items ) if( dam > 0 ) { break_glass( p, 16 ); ter_set( p, t_window_bars ); - spawn_item( p, "glass_shard", 5 ); + spawn_item( p, itype_glass_shard, 5 ); } } else if( terrain == t_window_boarded ) { dam -= rng( 10, 30 ); @@ -3618,7 +3636,7 @@ void map::shoot( const tripoint &p, projectile &proj, const bool hit_items ) if( one_in( 3 ) ) { break_glass( p, 16 ); ter_set( p, t_thconc_floor ); - spawn_item( p, "glass_shard", rng( 8, 16 ) ); + spawn_item( p, itype_glass_shard, rng( 8, 16 ) ); dam = 0; //Prevent damaging additional items, since we shot at the ceiling. } } else if( impassable( p ) && !is_transparent( p ) ) { @@ -4043,11 +4061,11 @@ void map::spawn_natural_artifact( const tripoint &p, artifact_natural_property p add_item_or_charges( p, item( new_natural_artifact( prop ), 0 ) ); } -void map::spawn_item( const tripoint &p, const std::string &type_id, +void map::spawn_item( const tripoint &p, const itype_id &type_id, const unsigned quantity, const int charges, const time_point &birthday, const int damlevel ) { - if( type_id == "null" ) { + if( type_id.is_null() ) { return; } @@ -4410,7 +4428,7 @@ static void process_vehicle_items( vehicle &cur_veh, int part ) if( n.is_battery() ) { n.set_energy( 1_kJ ); } else { - n.ammo_set( "battery", n.ammo_remaining() + 1 ); + n.ammo_set( itype_battery, n.ammo_remaining() + 1 ); } } power -= 1000; @@ -4826,11 +4844,11 @@ std::list map::use_charges( const tripoint &origin, const int range, const cata::optional cargo = vp.part_with_feature( "CARGO", true ); if( kpart ) { // we have a faucet, now to see what to drain - itype_id ftype = "null"; + itype_id ftype = itype_id::NULL_ID(); // Special case hotplates which draw battery power - if( type == "hotplate" ) { - ftype = "battery"; + if( type == itype_hotplate ) { + ftype = itype_battery; } else { ftype = type; } @@ -4848,12 +4866,12 @@ std::list map::use_charges( const tripoint &origin, const int range, } if( weldpart ) { // we have a weldrig, now to see what to drain - itype_id ftype = "null"; + itype_id ftype = itype_id::NULL_ID(); - if( type == "welder" ) { - ftype = "battery"; - } else if( type == "soldering_iron" ) { - ftype = "battery"; + if( type == itype_welder ) { + ftype = itype_battery; + } else if( type == itype_soldering_iron ) { + ftype = itype_battery; } // TODO: add a sane birthday arg item tmp( type, 0 ); @@ -4867,16 +4885,16 @@ std::list map::use_charges( const tripoint &origin, const int range, } if( craftpart ) { // we have a craftrig, now to see what to drain - itype_id ftype = "null"; + itype_id ftype = itype_id::NULL_ID(); - if( type == "press" ) { - ftype = "battery"; - } else if( type == "vac_sealer" ) { - ftype = "battery"; - } else if( type == "dehydrator" ) { - ftype = "battery"; - } else if( type == "food_processor" ) { - ftype = "battery"; + if( type == itype_press ) { + ftype = itype_battery; + } else if( type == itype_vac_sealer ) { + ftype = itype_battery; + } else if( type == itype_dehydrator ) { + ftype = itype_battery; + } else if( type == itype_food_processor ) { + ftype = itype_battery; } // TODO: add a sane birthday arg @@ -4891,10 +4909,10 @@ std::list map::use_charges( const tripoint &origin, const int range, } if( forgepart ) { // we have a veh_forge, now to see what to drain - itype_id ftype = "null"; + itype_id ftype = itype_id::NULL_ID(); - if( type == "forge" ) { - ftype = "battery"; + if( type == itype_forge ) { + ftype = itype_battery; } // TODO: add a sane birthday arg @@ -4909,10 +4927,10 @@ std::list map::use_charges( const tripoint &origin, const int range, } if( kilnpart ) { // we have a veh_kiln, now to see what to drain - itype_id ftype = "null"; + itype_id ftype = itype_id::NULL_ID(); - if( type == "kiln" ) { - ftype = "battery"; + if( type == itype_kiln ) { + ftype = itype_battery; } // TODO: add a sane birthday arg @@ -4927,14 +4945,14 @@ std::list map::use_charges( const tripoint &origin, const int range, } if( chempart ) { // we have a chem_lab, now to see what to drain - itype_id ftype = "null"; - - if( type == "chemistry_set" ) { - ftype = "battery"; - } else if( type == "hotplate" ) { - ftype = "battery"; - } else if( type == "electrolysis_kit" ) { - ftype = "battery"; + itype_id ftype = itype_id::NULL_ID(); + + if( type == itype_chemistry_set ) { + ftype = itype_battery; + } else if( type == itype_hotplate ) { + ftype = itype_battery; + } else if( type == itype_electrolysis_kit ) { + ftype = itype_battery; } // TODO: add a sane birthday arg diff --git a/src/map.h b/src/map.h index f4399d71138bd..ed1cae2c0883f 100644 --- a/src/map.h +++ b/src/map.h @@ -67,7 +67,6 @@ struct rl_vec2d; struct trap; enum class special_item_type : int; -using itype_id = std::string; class npc_template; class tileray; class vpart_reference; @@ -1009,9 +1008,22 @@ class map } void spawn_artifact( const tripoint &p ); void spawn_natural_artifact( const tripoint &p, artifact_natural_property prop ); - void spawn_item( const tripoint &p, const std::string &type_id, + void spawn_item( const tripoint &p, const itype_id &type_id, unsigned quantity = 1, int charges = 0, const time_point &birthday = calendar::start_of_cataclysm, int damlevel = 0 ); + void spawn_item( const point &p, const itype_id &type_id, + unsigned quantity = 1, int charges = 0, + const time_point &birthday = calendar::start_of_cataclysm, int damlevel = 0 ) { + spawn_item( tripoint( p, abs_sub.z ), type_id, quantity, charges, birthday, damlevel ); + } + + // FIXME: remove these overloads and require spawn_item to take an + // itype_id + void spawn_item( const tripoint &p, const std::string &type_id, + unsigned quantity = 1, int charges = 0, + const time_point &birthday = calendar::start_of_cataclysm, int damlevel = 0 ) { + spawn_item( p, itype_id( type_id ), quantity, charges, birthday, damlevel ); + } void spawn_item( const point &p, const std::string &type_id, unsigned quantity = 1, int charges = 0, const time_point &birthday = calendar::start_of_cataclysm, int damlevel = 0 ) { diff --git a/src/map_extras.cpp b/src/map_extras.cpp index afc4681bb9006..5a032e44814b4 100644 --- a/src/map_extras.cpp +++ b/src/map_extras.cpp @@ -68,6 +68,50 @@ static const std::string flag_SHRUB( "SHRUB" ); static const std::string flag_TREE( "TREE" ); static const std::string flag_YOUNG( "YOUNG" ); +static const itype_id itype_223_casing( "223_casing" ); +static const itype_id itype_762_51_casing( "762_51_casing" ); +static const itype_id itype_9mm_casing( "9mm_casing" ); +static const itype_id itype_acoustic_guitar( "acoustic_guitar" ); +static const itype_id itype_anbc_suit( "anbc_suit" ); +static const itype_id itype_ash( "ash" ); +static const itype_id itype_bag_canvas( "bag_canvas" ); +static const itype_id itype_bottle_glass( "bottle_glass" ); +static const itype_id itype_bullwhip( "bullwhip" ); +static const itype_id itype_chunk_sulfur( "chunk_sulfur" ); +static const itype_id itype_coke( "coke" ); +static const itype_id itype_crowbar( "crowbar" ); +static const itype_id itype_fedora( "fedora" ); +static const itype_id itype_glasses_eye( "glasses_eye" ); +static const itype_id itype_hatchet( "hatchet" ); +static const itype_id itype_heroin( "heroin" ); +static const itype_id itype_holybook_bible1( "holybook_bible1" ); +static const itype_id itype_indoor_volleyball( "indoor_volleyball" ); +static const itype_id itype_jacket_leather( "jacket_leather" ); +static const itype_id itype_katana( "katana" ); +static const itype_id itype_landmine( "landmine" ); +static const itype_id itype_machete( "machete" ); +static const itype_id itype_material_sand( "material_sand" ); +static const itype_id itype_material_soil( "material_soil" ); +static const itype_id itype_meth( "meth" ); +static const itype_id itype_rag_bloody( "rag_bloody" ); +static const itype_id itype_remington_870_breacher( "remington_870_breacher" ); +static const itype_id itype_shot_hull( "shot_hull" ); +static const itype_id itype_splinter( "splinter" ); +static const itype_id itype_stanag30( "stanag30" ); +static const itype_id itype_stick( "stick" ); +static const itype_id itype_stick_long( "stick_long" ); +static const itype_id itype_sunglasses( "sunglasses" ); +static const itype_id itype_sw_619( "sw_619" ); +static const itype_id itype_touring_suit( "touring_suit" ); +static const itype_id itype_tux( "tux" ); +static const itype_id itype_umbrella( "umbrella" ); +static const itype_id itype_usp_45( "usp_45" ); +static const itype_id itype_vodka( "vodka" ); +static const itype_id itype_weed( "weed" ); +static const itype_id itype_wheel( "wheel" ); +static const itype_id itype_withered( "withered" ); +static const itype_id itype_wrench( "wrench" ); + static const ter_str_id ter_dirt( "t_dirt" ); static const ter_str_id ter_grass_dead( "t_grass_dead" ); static const ter_str_id ter_stump( "t_stump" ); @@ -168,7 +212,7 @@ static void dead_vegetation_parser( map &m, const tripoint &loc ) if( fid.has_flag( flag_PLANT ) || fid.has_flag( flag_FLOWER ) || fid.has_flag( flag_ORGANIC ) ) { m.i_clear( loc ); m.furn_set( loc, f_null ); - m.spawn_item( loc, "withered" ); + m.spawn_item( loc, itype_withered ); } // terrain specific conversions const ter_id tid = m.ter( loc ); @@ -195,7 +239,7 @@ static void dead_vegetation_parser( map &m, const tripoint &loc ) if( tr.has_flag( flag_SHRUB ) ) { m.ter_set( loc, t_dirt ); if( one_in( 2 ) ) { - m.spawn_item( loc, "stick" ); + m.spawn_item( loc, itype_stick ); } } else if( tr.has_flag( flag_TREE ) ) { if( one_in( 4 ) ) { @@ -208,7 +252,7 @@ static void dead_vegetation_parser( map &m, const tripoint &loc ) } else if( tr.has_flag( flag_YOUNG ) ) { m.ter_set( loc, ter_dirt ); if( one_in( 2 ) ) { - m.spawn_item( loc, "stick_long" ); + m.spawn_item( loc, itype_stick_long ); } } } @@ -833,7 +877,7 @@ static bool mx_drugdeal( map &m, const tripoint &abs_sub ) case 1: // Weed num_drugs = rng( 20, 30 ); - drugtype = "weed"; + drugtype = itype_weed; break; case 2: case 3: @@ -841,20 +885,20 @@ static bool mx_drugdeal( map &m, const tripoint &abs_sub ) case 5: // Cocaine num_drugs = rng( 10, 20 ); - drugtype = "coke"; + drugtype = itype_coke; break; case 6: case 7: case 8: // Meth num_drugs = rng( 8, 14 ); - drugtype = "meth"; + drugtype = itype_meth; break; case 9: case 10: // Heroin num_drugs = rng( 6, 12 ); - drugtype = "heroin"; + drugtype = itype_heroin; break; } int num_bodies_a = dice( 3, 3 ); @@ -1088,7 +1132,7 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) //7.62x51mm casings left from m60 of the humvee for( const auto &loc : m.points_in_radius( { 6, 4, abs_sub.z }, 3, 0 ) ) { if( one_in( 4 ) ) { - m.spawn_item( loc, "762_51_casing" ); + m.spawn_item( loc, itype_762_51_casing ); } } @@ -1105,7 +1149,7 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) //5.56x45mm casings left from a soldier for( const auto &loc : m.points_in_radius( { 17, 4, abs_sub.z }, 2, 0 ) ) { if( one_in( 4 ) ) { - m.spawn_item( loc, "223_casing" ); + m.spawn_item( loc, itype_223_casing ); } } @@ -1121,7 +1165,7 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) std::vector empty_magazines_locations = line_to( point( 15, 5 ), point( 20, 5 ) ); for( auto &i : empty_magazines_locations ) { if( one_in( 3 ) ) { - m.spawn_item( { i, abs_sub.z }, "stanag30" ); + m.spawn_item( { i, abs_sub.z }, itype_stanag30 ); } } @@ -1213,14 +1257,14 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) //5.56x45mm casings left from a soldier for( const auto &loc : m.points_in_radius( { 9, 15, abs_sub.z }, 2, 0 ) ) { if( one_in( 4 ) ) { - m.spawn_item( loc, "223_casing" ); + m.spawn_item( loc, itype_223_casing ); } } //5.56x45mm casings left from another soldier for( const auto &loc : m.points_in_radius( { 15, 15, abs_sub.z }, 2, 0 ) ) { if( one_in( 4 ) ) { - m.spawn_item( loc, "223_casing" ); + m.spawn_item( loc, itype_223_casing ); } } @@ -1228,7 +1272,7 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) std::vector empty_magazines_locations = line_to( point( 5, 16 ), point( 18, 16 ) ); for( auto &i : empty_magazines_locations ) { if( one_in( 3 ) ) { - m.spawn_item( { i, abs_sub.z }, "stanag30" ); + m.spawn_item( { i, abs_sub.z }, itype_stanag30 ); } } @@ -1321,8 +1365,8 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) //Spill sand from damaged sandbags std::vector sandbag_positions = squares_in_direction( point( 10, 7 ), point( 11, 8 ) ); for( auto &i : sandbag_positions ) { - m.spawn_item( { i, abs_sub.z }, "bag_canvas", rng( 5, 13 ) ); - m.spawn_item( { i, abs_sub.z }, "material_sand", rng( 3, 8 ) ); + m.spawn_item( { i, abs_sub.z }, itype_bag_canvas, rng( 5, 13 ) ); + m.spawn_item( { i, abs_sub.z }, itype_material_sand, rng( 3, 8 ) ); } } else { m.put_items_from_loc( "army_bed", { 1, 6, abs_sub.z } ); @@ -1331,7 +1375,7 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) //5.56x45mm casings left from a soldier for( const auto &loc : m.points_in_radius( { 9, 8, abs_sub.z }, 2, 0 ) ) { if( one_in( 4 ) ) { - m.spawn_item( loc, "223_casing" ); + m.spawn_item( loc, itype_223_casing ); } } @@ -1339,7 +1383,7 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) std::vector empty_magazines_locations = line_to( point( 9, 3 ), point( 9, 13 ) ); for( auto &i : empty_magazines_locations ) { if( one_in( 3 ) ) { - m.spawn_item( { i, abs_sub.z }, "stanag30" ); + m.spawn_item( { i, abs_sub.z }, itype_stanag30 ); } } //Intact sandbag barricade @@ -1363,7 +1407,7 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) //5.56x45mm casings left from another soldier for( const auto &loc : m.points_in_radius( { 9, 18, abs_sub.z }, 2, 0 ) ) { if( one_in( 4 ) ) { - m.spawn_item( loc, "223_casing" ); + m.spawn_item( loc, itype_223_casing ); } } @@ -1371,7 +1415,7 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) std::vector empty_magazines_locations = line_to( point( 9, 16 ), point( 9, 20 ) ); for( auto &i : empty_magazines_locations ) { if( one_in( 3 ) ) { - m.spawn_item( { i, abs_sub.z }, "stanag30" ); + m.spawn_item( { i, abs_sub.z }, itype_stanag30 ); } } @@ -1443,7 +1487,7 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) //5.56x45mm casings left from soldiers for( const auto &loc : m.points_in_radius( { 15, 5, abs_sub.z }, 2, 0 ) ) { if( one_in( 4 ) ) { - m.spawn_item( loc, "223_casing" ); + m.spawn_item( loc, itype_223_casing ); } } @@ -1451,7 +1495,7 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) std::vector empty_magazines_locations = line_to( point( 15, 2 ), point( 15, 8 ) ); for( auto &i : empty_magazines_locations ) { if( one_in( 3 ) ) { - m.spawn_item( { i, abs_sub.z }, "stanag30" ); + m.spawn_item( { i, abs_sub.z }, itype_stanag30 ); } } @@ -1461,8 +1505,8 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) m.furn_set( { 17, 18, abs_sub.z }, f_crate_o ); //...and fill them with mines - m.spawn_item( { 16, 18, abs_sub.z }, "landmine", rng( 0, 5 ) ); - m.spawn_item( { 16, 19, abs_sub.z }, "landmine", rng( 0, 5 ) ); + m.spawn_item( { 16, 18, abs_sub.z }, itype_landmine, rng( 0, 5 ) ); + m.spawn_item( { 16, 19, abs_sub.z }, itype_landmine, rng( 0, 5 ) ); // Set some resting place with fire ring, camp chairs, tourist table and benches m.furn_set( { 20, 12, abs_sub.z }, f_crate_o ); @@ -1471,12 +1515,12 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) line_furn( &m, f_bench, point( 23, 11 ), point( 23, 13 ) ); line_furn( &m, f_camp_chair, point( 20, 14 ), point( 21, 14 ) ); - m.spawn_item( { 21, 12, abs_sub.z }, "splinter", rng( 5, 10 ) ); + m.spawn_item( { 21, 12, abs_sub.z }, itype_splinter, rng( 5, 10 ) ); //33% chance for an argument between drunk soldiers gone terribly wrong if( one_in( 3 ) ) { - m.spawn_item( { 22, 12, abs_sub.z }, "bottle_glass" ); - m.spawn_item( { 23, 11, abs_sub.z }, "hatchet" ); + m.spawn_item( { 22, 12, abs_sub.z }, itype_bottle_glass ); + m.spawn_item( { 23, 11, abs_sub.z }, itype_hatchet ); //Spawn chopped soldier corpse item body = item::make_corpse(); @@ -1486,7 +1530,7 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) //Spawn broken bench and splintered wood m.furn_set( { 23, 13, abs_sub.z }, f_null ); - m.spawn_item( { 23, 13, abs_sub.z }, "splinter", rng( 5, 10 ) ); + m.spawn_item( { 23, 13, abs_sub.z }, itype_splinter, rng( 5, 10 ) ); //Spawn blood for( const auto &loc : m.points_in_radius( { 23, 12, abs_sub.z }, 1, 0 ) ) { @@ -1498,9 +1542,9 @@ static bool mx_minefield( map &m, const tripoint &abs_sub ) m.place_items( "trash_cart", 80, { 19, 11, abs_sub.z }, { 21, 13, abs_sub.z }, false, calendar::start_of_cataclysm ); } else { - m.spawn_item( { 20, 11, abs_sub.z }, "hatchet" ); - m.spawn_item( { 22, 12, abs_sub.z }, "vodka" ); - m.spawn_item( { 20, 14, abs_sub.z }, "acoustic_guitar" ); + m.spawn_item( { 20, 11, abs_sub.z }, itype_hatchet ); + m.spawn_item( { 22, 12, abs_sub.z }, itype_vodka ); + m.spawn_item( { 20, 14, abs_sub.z }, itype_acoustic_guitar ); //Spawn trash in a crate m.place_items( "trash_cart", 80, { 20, 12, abs_sub.z }, { 20, 12, abs_sub.z }, false, @@ -1601,7 +1645,7 @@ static void place_fumarole( map &m, const point &p1, const point &p2, std::set

typeId() != "rock" || + if( pushee->typeId() != itype_rock || pushee->age() < 1_turns ) { pushee++; } else { @@ -1442,7 +1445,7 @@ void map::player_in_field( player &u ) } if( ft == fd_fire ) { // Heatsink or suit prevents ALL fire damage. - if( !u.has_active_bionic( bio_heatsink ) && !u.is_wearing( "rm13_armor_on" ) ) { + if( !u.has_active_bionic( bio_heatsink ) && !u.is_wearing( itype_rm13_armor_on ) ) { // To modify power of a field based on... whatever is relevant for the effect. int adjusted_intensity = cur.get_field_intensity(); @@ -1563,7 +1566,7 @@ void map::player_in_field( player &u ) // Fireballs can't touch you inside a car. // Heatsink or suit stops fire. if( !u.has_active_bionic( bio_heatsink ) && - !u.is_wearing( "rm13_armor_on" ) ) { + !u.is_wearing( itype_rm13_armor_on ) ) { u.add_msg_player_or_npc( m_bad, _( "You're torched by flames!" ), _( " is torched by flames!" ) ); u.deal_damage( nullptr, bodypart_id( "leg_l" ), damage_instance( DT_HEAT, rng( 2, 6 ) ) ); diff --git a/src/mapdata.cpp b/src/mapdata.cpp index c4c6e532b1b58..f60526a8b849d 100644 --- a/src/mapdata.cpp +++ b/src/mapdata.cpp @@ -1276,7 +1276,7 @@ void furn_t::load( const JsonObject &jo, const std::string &src ) optional( jo, was_loaded, "keg_capacity", keg_capacity, legacy_volume_reader, 0_ml ); mandatory( jo, was_loaded, "required_str", move_str_req ); optional( jo, was_loaded, "max_volume", max_volume, volume_reader(), DEFAULT_MAX_VOLUME_IN_SQUARE ); - optional( jo, was_loaded, "crafting_pseudo_item", crafting_pseudo_item, "" ); + optional( jo, was_loaded, "crafting_pseudo_item", crafting_pseudo_item, itype_id() ); optional( jo, was_loaded, "deployed_item", deployed_item ); load_symbol( jo ); transparent = false; diff --git a/src/mapdata.h b/src/mapdata.h index 32d075d6f9975..c94e6fead708e 100644 --- a/src/mapdata.h +++ b/src/mapdata.h @@ -25,8 +25,6 @@ struct tripoint; using iexamine_function = void ( * )( player &, const tripoint & ); -using itype_id = std::string; - struct map_bash_info { int str_min; // min str(*) required to bash int str_max; // max str required: bash succeeds if str >= random # between str_min & str_max @@ -363,7 +361,7 @@ struct furn_t : map_data_common_t { furn_str_id id; furn_str_id open; // Open action: transform into furniture with matching id furn_str_id close; // Close action: transform into furniture with matching id - std::string crafting_pseudo_item; + itype_id crafting_pseudo_item; units::volume keg_capacity = 0_ml; int comfort = 0; int floor_bedding_warmth = 0; diff --git a/src/mapgen.cpp b/src/mapgen.cpp index d3b70621fe1e7..33c590a91c1de 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -1159,23 +1159,24 @@ class jmapgen_loot : public jmapgen_piece jsi.get_int( "magazine", 0 ) ) , chance( jsi.get_int( "chance", 100 ) ) { const std::string group = jsi.get_string( "group", std::string() ); - const std::string name = jsi.get_string( "item", std::string() ); + itype_id ity; + jsi.read( "item", ity ); - if( group.empty() == name.empty() ) { + if( group.empty() == ity.is_empty() ) { jsi.throw_error( "must provide either item or group" ); } if( !group.empty() && !item_group::group_is_defined( group ) ) { set_mapgen_defer( jsi, "group", "no such item group" ); } - if( !name.empty() && !item::type_is_defined( name ) ) { - set_mapgen_defer( jsi, "item", "no such item type '" + name + "'" ); + if( !ity.is_empty() && !item::type_is_defined( ity ) ) { + set_mapgen_defer( jsi, "item", "no such item type '" + ity.str() + "'" ); } // All the probabilities are 100 because we do the roll in @ref apply. if( group.empty() ) { // Migrations are applied to item *groups* on load, but single item spawns must be // migrated individually - result_group.add_item_entry( item_controller->migrate_id( name ), 100 ); + result_group.add_item_entry( item_controller->migrate_id( ity ), 100 ); } else { result_group.add_group_entry( group, 100 ); } @@ -1639,7 +1640,7 @@ class jmapgen_sealed_item : public jmapgen_piece const itype *spawned_type = item::find_type( item_spawner->type ); if( !spawned_type->seed ) { debugmsg( "%s (with flag PLANT) spawns item type %s which is not a seed.", - summary, spawned_type->get_id() ); + summary, spawned_type->get_id().str() ); return; } } @@ -1657,7 +1658,7 @@ class jmapgen_sealed_item : public jmapgen_piece if( !type->seed ) { debugmsg( "%s (with flag PLANT) spawns item group %s which can " "spawn item %s which is not a seed.", - summary, group_id, type->get_id() ); + summary, group_id, type->get_id().str() ); return; } } diff --git a/src/mapgen_functions.cpp b/src/mapgen_functions.cpp index 5d94ca4d103ef..cf748e1792363 100644 --- a/src/mapgen_functions.cpp +++ b/src/mapgen_functions.cpp @@ -36,6 +36,10 @@ #include "vehicle_group.h" #include "weighted_list.h" +static const itype_id itype_hat_hard( "hat_hard" ); +static const itype_id itype_jackhammer( "jackhammer" ); +static const itype_id itype_mask_dust( "mask_dust" ); + static const mtype_id mon_ant_larva( "mon_ant_larva" ); static const mtype_id mon_ant_queen( "mon_ant_queen" ); static const mtype_id mon_bat( "mon_bat" ); @@ -1973,13 +1977,13 @@ void mapgen_cavern( mapgendata &dat ) y = rng( 0, SEEY * 2 - 1 ); } while( m->impassable( point( x, y ) ) ); if( !one_in( 3 ) ) { - m->spawn_item( point( x, y ), "jackhammer" ); + m->spawn_item( point( x, y ), itype_jackhammer ); } if( one_in( 3 ) ) { - m->spawn_item( point( x, y ), "mask_dust" ); + m->spawn_item( point( x, y ), itype_mask_dust ); } if( one_in( 2 ) ) { - m->spawn_item( point( x, y ), "hat_hard" ); + m->spawn_item( point( x, y ), itype_hat_hard ); } while( !one_in( 3 ) ) { for( int i = 0; i < 3; ++i ) { diff --git a/src/martialarts.cpp b/src/martialarts.cpp index a881ae6f1c2d2..13acf49f18998 100644 --- a/src/martialarts.cpp +++ b/src/martialarts.cpp @@ -58,7 +58,7 @@ matype_id martial_art_learned_from( const itype &type ) if( !type.book || type.book->martial_art.is_null() ) { debugmsg( "Item '%s' which claims to teach a martial art is missing martial_art", - type.get_id() ); + type.get_id().str() ); return {}; } @@ -1463,7 +1463,7 @@ bool ma_style_callback::key( const input_context &ctxt, const input_event &event if( !ma.weapons.empty() ) { std::vector weapons; std::transform( ma.weapons.begin(), ma.weapons.end(), - std::back_inserter( weapons ), []( const std::string & wid )-> std::string { return item::nname( wid ); } ); + std::back_inserter( weapons ), []( const itype_id & wid )-> std::string { return item::nname( wid ); } ); // Sorting alphabetically makes it easier to find a specific weapon std::sort( weapons.begin(), weapons.end(), localized_compare ); // This removes duplicate names (e.g. a real weapon and a replica sharing the same name) from the weapon list. diff --git a/src/martialarts.h b/src/martialarts.h index f78c91b8cb311..8355178d5eba5 100644 --- a/src/martialarts.h +++ b/src/martialarts.h @@ -232,7 +232,7 @@ class martialart // determines if a technique is valid or not for this style bool has_technique( const Character &u, const matec_id &tec_id ) const; // determines if a weapon is valid for this style - bool has_weapon( const std::string &itt ) const; + bool has_weapon( const itype_id & ) const; // Is this weapon OK with this art? bool weapon_valid( const item &it ) const; // Getter for Character style change message @@ -253,7 +253,7 @@ class martialart bool arm_block_with_bio_armor_arms = false; bool leg_block_with_bio_armor_legs = false; std::set techniques; // all available techniques - std::set weapons; // all style weapons + std::set weapons; // all style weapons bool strictly_unarmed = false; // Punch daggers etc. bool strictly_melee = false; // Must have a weapon. bool allow_melee = false; // Can use unarmed or with ANY weapon diff --git a/src/material.cpp b/src/material.cpp index 801621f5cd631..79eadb59442a2 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -74,7 +74,7 @@ void material_type::load( const JsonObject &jsobj, const std::string & ) optional( jsobj, was_loaded, "freeze_point", _freeze_point ); assign( jsobj, "salvaged_into", _salvaged_into ); - optional( jsobj, was_loaded, "repaired_with", _repaired_with, "null" ); + optional( jsobj, was_loaded, "repaired_with", _repaired_with, itype_id::NULL_ID() ); optional( jsobj, was_loaded, "edible", _edible, false ); optional( jsobj, was_loaded, "rotting", _rotting, false ); optional( jsobj, was_loaded, "soft", _soft, false ); @@ -103,13 +103,11 @@ void material_type::load( const JsonObject &jsobj, const std::string & ) _burn_data.emplace_back( mbd ); } - for( JsonArray pair : jsobj.get_array( "burn_products" ) ) { - _burn_products.emplace_back( pair.get_string( 0 ), static_cast< float >( pair.get_float( 1 ) ) ); - } + jsobj.read( "burn_products", _burn_products, true ); optional( jsobj, was_loaded, "compact_accepts", _compact_accepts, auto_flags_reader() ); - optional( jsobj, was_loaded, "compacts_into", _compacts_into, string_reader() ); + optional( jsobj, was_loaded, "compacts_into", _compacts_into, auto_flags_reader() ); } void material_type::check() const @@ -120,7 +118,7 @@ void material_type::check() const if( _dmg_adj.size() < 4 ) { debugmsg( "material %s specifies insufficient damaged adjectives.", id.c_str() ); } - if( _salvaged_into && ( !item::type_is_defined( *_salvaged_into ) || *_salvaged_into == "null" ) ) { + if( _salvaged_into && ( !item::type_is_defined( *_salvaged_into ) || _salvaged_into->is_null() ) ) { debugmsg( "invalid \"salvaged_into\" %s for %s.", _salvaged_into->c_str(), id.c_str() ); } if( !item::type_is_defined( _repaired_with ) ) { diff --git a/src/material.h b/src/material.h index 1975443bdb969..4e1e5d59c0129 100644 --- a/src/material.h +++ b/src/material.h @@ -17,7 +17,6 @@ class material_type; enum damage_type : int; -using itype_id = std::string; class JsonObject; using mat_burn_products = std::vector>; diff --git a/src/mattack_actors.cpp b/src/mattack_actors.cpp index 7cc77f9ab38ab..d5b1620177683 100644 --- a/src/mattack_actors.cpp +++ b/src/mattack_actors.cpp @@ -384,7 +384,7 @@ gun_actor::gun_actor() : description( _( "The %1$s fires its %2$s!" ) ), void gun_actor::load_internal( const JsonObject &obj, const std::string & ) { - gun_type = obj.get_string( "gun_type" ); + obj.read( "gun_type", gun_type, true ); obj.read( "ammo_type", ammo_type ); @@ -529,8 +529,8 @@ void gun_actor::shoot( monster &z, Creature &target, const gun_mode_id &mode ) c item gun( gun_type ); gun.gun_set_mode( mode ); - itype_id ammo = ( ammo_type != "null" ) ? ammo_type : gun.ammo_default(); - if( ammo != "null" ) { + itype_id ammo = ammo_type.is_null() ? gun.ammo_default() : ammo_type; + if( !ammo.is_null() ) { gun.ammo_set( ammo, z.ammo[ ammo ] ); } diff --git a/src/mattack_actors.h b/src/mattack_actors.h index cb0e202ca1feb..8f7f06f6e3c7f 100644 --- a/src/mattack_actors.h +++ b/src/mattack_actors.h @@ -133,7 +133,7 @@ class gun_actor : public mattack_actor itype_id gun_type; /** Specific ammo type to use or for gun default if unspecified */ - itype_id ammo_type = "null"; + itype_id ammo_type = itype_id::NULL_ID(); /*@{*/ /** Balanced against player. If fake_skills unspecified defaults to GUN 4, WEAPON 8 */ diff --git a/src/melee.cpp b/src/melee.cpp index 0d602c47885ab..30b0a04922ad4 100644 --- a/src/melee.cpp +++ b/src/melee.cpp @@ -65,6 +65,10 @@ static const bionic_id bio_cqb( "bio_cqb" ); static const bionic_id bio_memory( "bio_memory" ); +static const itype_id itype_fur( "fur" ); +static const itype_id itype_leather( "leather" ); +static const itype_id itype_rag( "rag" ); + static const matec_id tec_none( "tec_none" ); static const matec_id WBLOCK_1( "WBLOCK_1" ); static const matec_id WBLOCK_2( "WBLOCK_2" ); @@ -181,7 +185,7 @@ bool Character::handle_melee_wear( item &shield, float wear_multiplier ) float material_factor; itype_id weak_comp; - itype_id big_comp = "null"; + itype_id big_comp = itype_id::NULL_ID(); // Fragile items that fall apart easily when used as a weapon due to poor construction quality if( shield.has_flag( "FRAGILE_MELEE" ) ) { const float fragile_factor = 6; @@ -189,10 +193,7 @@ bool Character::handle_melee_wear( item &shield, float wear_multiplier ) units::volume big_vol = 0_ml; // Items that should have no bearing on durability - const std::set blacklist = { "rag", - "leather", - "fur" - }; + const std::set blacklist = { itype_rag, itype_leather, itype_fur }; for( auto &comp : shield.components ) { if( blacklist.count( comp.typeId() ) <= 0 ) { @@ -2219,7 +2220,7 @@ double player::weapon_value( const item &weap, int ammo ) const // A small bonus for guns you can also use to hit stuff with (bayonets etc.) const double my_val = more + ( less / 2.0 ); - add_msg( m_debug, "%s (%ld ammo) sum value: %.1f", weap.type->get_id(), ammo, my_val ); + add_msg( m_debug, "%s (%ld ammo) sum value: %.1f", weap.type->get_id().str(), ammo, my_val ); if( is_wielding( weap ) ) { cached_info.emplace( "weapon_value", my_val ); } @@ -2246,7 +2247,7 @@ double player::melee_value( const item &weap ) const my_value *= 1.5; } - add_msg( m_debug, "%s as melee: %.1f", weap.type->get_id(), my_value ); + add_msg( m_debug, "%s as melee: %.1f", weap.type->get_id().str(), my_value ); return std::max( 0.0, my_value ); } diff --git a/src/mission.cpp b/src/mission.cpp index 72359f5caeb81..0fd633679f6d4 100644 --- a/src/mission.cpp +++ b/src/mission.cpp @@ -295,7 +295,7 @@ void mission::wrap_up() tmp_inv.dump( items ); Group_tag grp_type = type->group_id; itype_id container = type->container_id; - bool specific_container_required = container != "null"; + bool specific_container_required = !container.is_null(); bool remove_container = type->remove_container; itype_id empty_container = type->empty_container; @@ -304,9 +304,8 @@ void mission::wrap_up() items, grp_type, matches, container, itype_id( "null" ), specific_container_required ); - std::map::iterator cnt_it; - for( cnt_it = matches.begin(); cnt_it != matches.end(); cnt_it++ ) { - comps.push_back( item_comp( cnt_it->first, cnt_it->second ) ); + for( std::pair &cnt : matches ) { + comps.push_back( item_comp( cnt.first, cnt.second ) ); } @@ -314,7 +313,7 @@ void mission::wrap_up() if( remove_container ) { std::vector container_comp = std::vector(); - if( empty_container != "null" ) { + if( !empty_container.is_null() ) { container_comp.push_back( item_comp( empty_container, type->item_count ) ); u.consume_items( container_comp ); } else { @@ -364,7 +363,7 @@ bool mission::is_complete( const character_id &_npc_id ) const tmp_inv.dump( items ); Group_tag grp_type = type->group_id; itype_id container = type->container_id; - bool specific_container_required = container != "null"; + bool specific_container_required = !container.is_null(); std::map matches = std::map(); get_all_item_group_matches( @@ -372,7 +371,7 @@ bool mission::is_complete( const character_id &_npc_id ) const container, itype_id( "null" ), specific_container_required ); int total_match = std::accumulate( matches.begin(), matches.end(), 0, - []( const std::size_t previous, const std::pair &p ) { + []( const std::size_t previous, const std::pair &p ) { return static_cast( previous + p.second ); } ); @@ -479,7 +478,7 @@ void mission::get_all_item_group_matches( std::vector &items, //check whether item itself is target if( item_in_group && correct_container ) { - std::map::iterator it = matches.find( itm->typeId() ); + std::map::iterator it = matches.find( itm->typeId() ); if( it != matches.end() ) { it->second = ( it->second ) + 1; } else { @@ -562,7 +561,7 @@ int mission::get_id() const return uid; } -const std::string &mission::get_item_id() const +const itype_id &mission::get_item_id() const { return item_id; } @@ -595,7 +594,7 @@ character_id mission::get_npc_id() const return npc_id; } -const std::vector> &mission::get_likely_rewards() const +const std::vector> &mission::get_likely_rewards() const { return type->likely_rewards; } @@ -688,7 +687,7 @@ mission::mission() value = 0; uid = -1; target = tripoint_min; - item_id = "null"; + item_id = itype_id::NULL_ID(); item_count = 1; target_id = string_id::NULL_ID(); recruit_class = NC_NONE; diff --git a/src/mission.h b/src/mission.h index edc510edcabb6..f81e02e465784 100644 --- a/src/mission.h +++ b/src/mission.h @@ -219,15 +219,15 @@ struct mission_type { bool has_generic_rewards = true; // A limited subset of the talk_effects on the mission - std::vector> likely_rewards; + std::vector> likely_rewards; // Points of origin std::vector origins; - itype_id item_id = "null"; + itype_id item_id = itype_id::NULL_ID(); Group_tag group_id = "null"; - itype_id container_id = "null"; + itype_id container_id = itype_id::NULL_ID(); bool remove_container = false; - itype_id empty_container = "null"; + itype_id empty_container = itype_id::NULL_ID(); int item_count = 1; npc_class_id recruit_class = npc_class_id( "NC_NONE" ); // The type of NPC you are to recruit character_id target_npc_id; @@ -363,9 +363,9 @@ class mission mission_type_id get_follow_up() const; int get_value() const; int get_id() const; - const std::string &get_item_id() const; + const itype_id &get_item_id() const; character_id get_npc_id() const; - const std::vector> &get_likely_rewards() const; + const std::vector> &get_likely_rewards() const; bool has_generic_rewards() const; /** * Whether the mission is assigned to a player character. If not, the mission is free and diff --git a/src/mission_companion.cpp b/src/mission_companion.cpp index 6cda4f10cc53b..369489ab97f43 100644 --- a/src/mission_companion.cpp +++ b/src/mission_companion.cpp @@ -64,6 +64,9 @@ static const efftype_id effect_riding( "riding" ); +static const itype_id itype_fungal_seeds( "fungal_seeds" ); +static const itype_id itype_marloss_seed( "marloss_seed" ); + static const skill_id skill_bashing( "bashing" ); static const skill_id skill_cutting( "cutting" ); static const skill_id skill_dodge( "dodge" ); @@ -966,7 +969,8 @@ void talk_function::field_plant( npc &p, const std::string &place ) return; } std::vector seed_inv = g->u.items_with( []( const item & itm ) { - return itm.is_seed() && itm.typeId() != "marloss_seed" && itm.typeId() != "fungal_seeds"; + return itm.is_seed() && itm.typeId() != itype_marloss_seed && + itm.typeId() != itype_fungal_seeds; } ); if( seed_inv.empty() ) { popup( _( "You have no seeds to plant!" ) ); diff --git a/src/mission_start.cpp b/src/mission_start.cpp index ccf6d8a2b27f4..8ec3f52507ec5 100644 --- a/src/mission_start.cpp +++ b/src/mission_start.cpp @@ -27,8 +27,12 @@ #include "string_formatter.h" #include "translations.h" -static const mtype_id mon_dog( "mon_dog" ); +static const itype_id itype_software_hacking( "software_hacking" ); +static const itype_id itype_software_math( "software_math" ); +static const itype_id itype_software_medical( "software_medical" ); +static const itype_id itype_software_useless( "software_useless" ); +static const mtype_id mon_dog( "mon_dog" ); static const mtype_id mon_zombie( "mon_zombie" ); static const mtype_id mon_zombie_brute( "mon_zombie_brute" ); static const mtype_id mon_zombie_dog( "mon_zombie_dog" ); @@ -194,15 +198,15 @@ void mission_start::place_npc_software( mission *miss ) std::string type = "house"; if( dev->myclass == NC_HACKER ) { - miss->item_id = "software_hacking"; + miss->item_id = itype_software_hacking; } else if( dev->myclass == NC_DOCTOR ) { - miss->item_id = "software_medical"; + miss->item_id = itype_software_medical; type = "s_pharm"; miss->follow_up = mission_type_id( "MISSION_GET_ZOMBIE_BLOOD_ANAL" ); } else if( dev->myclass == NC_SCIENTIST ) { - miss->item_id = "software_math"; + miss->item_id = itype_software_math; } else { - miss->item_id = "software_useless"; + miss->item_id = itype_software_useless; } tripoint place; diff --git a/src/mission_ui.cpp b/src/mission_ui.cpp index e40dd206e7c4c..fcb70ca7a1c5e 100644 --- a/src/mission_ui.cpp +++ b/src/mission_ui.cpp @@ -104,10 +104,10 @@ void game::list_missions() miss->name() + for_npc ); auto format_tokenized_description = []( const std::string & description, - const std::vector> &rewards ) { + const std::vector> &rewards ) { std::string formatted_description = description; for( const auto &reward : rewards ) { - std::string token = ""; + std::string token = ""; formatted_description = string_replace( formatted_description, token, string_format( "%d", reward.first ) ); } diff --git a/src/missiondef.cpp b/src/missiondef.cpp index c6fbc4e029e73..f6da779457fcd 100644 --- a/src/missiondef.cpp +++ b/src/missiondef.cpp @@ -345,7 +345,7 @@ void mission_type::finalize() void mission_type::check_consistency() { for( const auto &m : get_all() ) { - if( !m.item_id.empty() && !item::type_is_defined( m.item_id ) ) { + if( !m.item_id.is_empty() && !item::type_is_defined( m.item_id ) ) { debugmsg( "Mission %s has undefined item id %s", m.id.c_str(), m.item_id.c_str() ); } } diff --git a/src/monattack.cpp b/src/monattack.cpp index a95150298bf45..b438b98cd96c7 100644 --- a/src/monattack.cpp +++ b/src/monattack.cpp @@ -121,6 +121,26 @@ static const efftype_id effect_targeted( "targeted" ); static const efftype_id effect_tindrift( "tindrift" ); static const efftype_id effect_under_op( "under_operation" ); +static const itype_id itype_ant_egg( "ant_egg" ); +static const itype_id itype_badge_cybercop( "badge_cybercop" ); +static const itype_id itype_badge_deputy( "badge_deputy" ); +static const itype_id itype_badge_detective( "badge_detective" ); +static const itype_id itype_badge_doctor( "badge_doctor" ); +static const itype_id itype_badge_marshal( "badge_marshal" ); +static const itype_id itype_badge_swat( "badge_swat" ); +static const itype_id itype_bot_c4_hack( "bot_c4_hack" ); +static const itype_id itype_bot_flashbang_hack( "bot_flashbang_hack" ); +static const itype_id itype_bot_gasbomb_hack( "bot_gasbomb_hack" ); +static const itype_id itype_bot_grenade_hack( "bot_grenade_hack" ); +static const itype_id itype_bot_manhack( "bot_manhack" ); +static const itype_id itype_bot_mininuke_hack( "bot_mininuke_hack" ); +static const itype_id itype_bot_pacification_hack( "bot_pacification_hack" ); +static const itype_id itype_c4( "c4" ); +static const itype_id itype_c4armed( "c4armed" ); +static const itype_id itype_e_handcuffs( "e_handcuffs" ); +static const itype_id itype_mininuke( "mininuke" ); +static const itype_id itype_mininuke_act( "mininuke_act" ); + static const skill_id skill_gun( "gun" ); static const skill_id skill_launcher( "launcher" ); static const skill_id skill_melee( "melee" ); @@ -361,7 +381,7 @@ bool mattack::antqueen( monster *z ) if( g->is_empty( dest ) && g->m.has_items( dest ) ) { for( auto &i : g->m.i_at( dest ) ) { - if( i.typeId() == "ant_egg" ) { + if( i.typeId() == itype_ant_egg ) { egg_points.push_back( dest ); // Done looking at this tile break; @@ -395,7 +415,7 @@ bool mattack::antqueen( monster *z ) for( const tripoint &egg_pos : egg_points ) { map_stack items = g->m.i_at( egg_pos ); for( map_stack::iterator it = items.begin(); it != items.end(); ) { - if( it->typeId() != "ant_egg" ) { + if( it->typeId() != itype_ant_egg ) { ++it; continue; } @@ -1241,7 +1261,7 @@ bool mattack::science( monster *const z ) // I said SCIENCE again! const size_t empty_neighbor_count = empty_neighbors.second; if( empty_neighbor_count ) { - if( z->ammo["bot_manhack"] > 0 ) { + if( z->ammo[itype_bot_manhack] > 0 ) { valid_attacks[valid_attack_count++] = att_manhack; } valid_attacks[valid_attack_count++] = att_acid_pool; @@ -1304,7 +1324,7 @@ bool mattack::science( monster *const z ) // I said SCIENCE again! break; case att_manhack : { z->moves -= att_cost_manhack; - z->ammo["bot_manhack"]--; + z->ammo[itype_bot_manhack]--; // if the player can see it if( g->u.sees( *z ) ) { @@ -2975,7 +2995,7 @@ bool mattack::nurse_assist( monster *z ) } if( found_target ) { - if( target->is_wearing( "badge_doctor" ) || + if( target->is_wearing( itype_badge_doctor ) || z->attitude_to( *target ) == Creature::Attitude::A_FRIENDLY ) { sounds::sound( z->pos(), 8, sounds::sound_t::electronic_speech, string_format( @@ -2989,7 +3009,7 @@ bool mattack::nurse_assist( monster *z ) } bool mattack::nurse_operate( monster *z ) { - const std::string ammo_type( "anesthetic" ); + const itype_id ammo_type( "anesthetic" ); if( z->has_effect( effect_dragging ) || z->has_effect( effect_operating ) ) { return false; @@ -3000,7 +3020,7 @@ bool mattack::nurse_operate( monster *z ) add_msg( m_info, _( "The %s is scanning its surroundings." ), z->name() ); } - if( ( ( g->u.is_wearing( "badge_doctor" ) || + if( ( ( g->u.is_wearing( itype_badge_doctor ) || z->attitude_to( g->u ) == Creature::Attitude::A_FRIENDLY ) && u_see ) && one_in( 100 ) ) { add_msg( m_info, _( "The %s doesn't seem to register you as a doctor." ), z->name() ); @@ -3145,7 +3165,7 @@ bool mattack::photograph( monster *z ) // If you are in fact listed as a police officer if( g->u.has_trait( trait_PROF_POLICE ) ) { // And you're wearing your badge - if( g->u.is_wearing( "badge_deputy" ) ) { + if( g->u.is_wearing( itype_badge_deputy ) ) { if( one_in( 3 ) ) { add_msg( m_info, _( "The %s flashes a LED and departs. Human officer on scene." ), z->name() ); @@ -3165,7 +3185,7 @@ bool mattack::photograph( monster *z ) if( g->u.has_trait( trait_PROF_PD_DET ) ) { // And you have your shield on - if( g->u.is_wearing( "badge_detective" ) ) { + if( g->u.is_wearing( itype_badge_detective ) ) { if( one_in( 4 ) ) { add_msg( m_info, _( "The %s flashes a LED and departs. Human officer on scene." ), z->name() ); @@ -3183,7 +3203,7 @@ bool mattack::photograph( monster *z ) } } else if( g->u.has_trait( trait_PROF_SWAT ) ) { // And you're wearing your badge - if( g->u.is_wearing( "badge_swat" ) ) { + if( g->u.is_wearing( itype_badge_swat ) ) { if( one_in( 3 ) ) { add_msg( m_info, _( "The %s flashes a LED and departs. SWAT's working the area." ), z->name() ); @@ -3200,7 +3220,7 @@ bool mattack::photograph( monster *z ) } } else if( g->u.has_trait( trait_PROF_CYBERCO ) ) { // And you're wearing your badge - if( g->u.is_wearing( "badge_cybercop" ) ) { + if( g->u.is_wearing( itype_badge_cybercop ) ) { if( one_in( 3 ) ) { add_msg( m_info, _( "The %s winks a LED and departs. One machine to another?" ), z->name() ); @@ -3220,7 +3240,7 @@ bool mattack::photograph( monster *z ) if( g->u.has_trait( trait_PROF_FED ) ) { // And you're wearing your badge - if( g->u.is_wearing( "badge_marshal" ) ) { + if( g->u.is_wearing( itype_badge_marshal ) ) { add_msg( m_info, _( "The %s flashes a LED and departs. The Feds got this." ), z->name() ); z->no_corpse_quiet = true; z->no_extra_death_drops = true; @@ -3229,7 +3249,7 @@ bool mattack::photograph( monster *z ) } } - if( z->friendly || g->u.weapon.typeId() == "e_handcuffs" ) { + if( z->friendly || g->u.weapon.typeId() == itype_e_handcuffs ) { // Friendly (hacked?) bot ignore the player. Arrested suspect ignored too. // TODO: might need to be revisited when it can target npcs. return false; @@ -3298,7 +3318,7 @@ void mattack::taze( monster *z, Creature *target ) void mattack::rifle( monster *z, Creature *target ) { - const std::string ammo_type( "556" ); + const itype_id ammo_type( "556" ); // Make sure our ammo isn't weird. if( z->ammo[ammo_type] > 3000 ) { debugmsg( "Generated too much ammo (%d) for %s in mattack::rifle", z->ammo[ammo_type], @@ -3347,7 +3367,7 @@ void mattack::rifle( monster *z, Creature *target ) void mattack::frag( monster *z, Creature *target ) // This is for the bots, not a standalone turret { - const std::string ammo_type( "40x46mm_m433" ); + const itype_id ammo_type( "40x46mm_m433" ); // Make sure our ammo isn't weird. if( z->ammo[ammo_type] > 200 ) { debugmsg( "Generated too much ammo (%d) for %s in mattack::frag", z->ammo[ammo_type], @@ -3407,7 +3427,7 @@ void mattack::frag( monster *z, Creature *target ) // This is for the bots, not void mattack::tankgun( monster *z, Creature *target ) { - const std::string ammo_type( "120mm_HEAT" ); + const itype_id ammo_type( "120mm_HEAT" ); // Make sure our ammo isn't weird. if( z->ammo[ammo_type] > 40 ) { debugmsg( "Generated too much ammo (%d) for %s in mattack::tankgun", z->ammo[ammo_type], @@ -3746,7 +3766,7 @@ bool mattack::copbot( monster *z ) // TODO: Make it recognize zeds as human, but ignore animals player *foe = dynamic_cast( target ); bool sees_u = foe != nullptr && z->sees( *foe ); - bool cuffed = foe != nullptr && foe->weapon.typeId() == "e_handcuffs"; + bool cuffed = foe != nullptr && foe->weapon.typeId() == itype_e_handcuffs; // Taze first, then ask questions (simplifies later checks for non-humans) if( !cuffed && is_adjacent( z, target, true ) ) { taze( z, target ); @@ -4684,7 +4704,7 @@ bool mattack::riotbot( monster *z ) //already arrested? //and yes, if the player has no hands, we are not going to arrest him. if( foe != nullptr && - ( foe->weapon.typeId() == "e_handcuffs" || !foe->has_two_arms() ) ) { + ( foe->weapon.typeId() == itype_e_handcuffs || !foe->has_two_arms() ) ) { z->anger = 0; if( calendar::once_every( 25_turns ) ) { @@ -5395,11 +5415,11 @@ bool mattack::kamikaze( monster *z ) const itype *act_bomb_type; int charges; // Hardcoded data for charge variant items - if( z->ammo.begin()->first == "mininuke" ) { - act_bomb_type = item::find_type( "mininuke_act" ); + if( z->ammo.begin()->first == itype_mininuke ) { + act_bomb_type = item::find_type( itype_mininuke_act ); charges = 20; - } else if( z->ammo.begin()->first == "c4" ) { - act_bomb_type = item::find_type( "c4armed" ); + } else if( z->ammo.begin()->first == itype_c4 ) { + act_bomb_type = item::find_type( itype_c4armed ); charges = 10; } else { auto usage = bomb_type->get_use( "transform" ); @@ -5526,7 +5546,7 @@ struct grenade_helper_struct { // Returns 0 if this should be retired, 1 if it was successful, and -1 if something went horribly wrong static int grenade_helper( monster *const z, Creature *const target, const int dist, - const int moves, std::map data ) + const int moves, std::map data ) { // Can't do anything if we can't act if( !z->can_act() ) { @@ -5568,13 +5588,13 @@ static int grenade_helper( monster *const z, Creature *const target, const int d // Hey look! another weighted list! // Grab all attacks that pass their chance check and we've spent enough ammo for - weighted_float_list possible_attacks; + weighted_float_list possible_attacks; for( const auto &amm : z->ammo ) { if( amm.second > 0 && data[amm.first].ammo_percentage >= rat ) { possible_attacks.add( amm.first, 1.0 / data[amm.first].chance ); } } - std::string att = *possible_attacks.pick(); + itype_id att = *possible_attacks.pick(); z->moves -= moves; z->ammo[att]--; @@ -5614,19 +5634,19 @@ static int grenade_helper( monster *const z, Creature *const target, const int d bool mattack::grenadier( monster *const z ) { // Build our grenade map - std::map grenades; + std::map grenades; // Grenades - grenades["bot_pacification_hack"].message = + grenades[itype_bot_pacification_hack].message = _( "The %s deploys a pacification hack!" ); // Flashbangs - grenades["bot_flashbang_hack"].message = + grenades[itype_bot_flashbang_hack].message = _( "The %s deploys a flashbang hack!" ); // Gasbombs - grenades["bot_gasbomb_hack"].message = + grenades[itype_bot_gasbomb_hack].message = _( "The %s deploys a tear gas hack!" ); // C-4 - grenades["bot_c4_hack"].message = _( "The %s buzzes and deploys a C-4 hack!" ); - grenades["bot_c4_hack"].chance = 8; + grenades[itype_bot_c4_hack].message = _( "The %s buzzes and deploys a C-4 hack!" ); + grenades[itype_bot_c4_hack].chance = 8; // Only can actively target the player right now. Once we have the ability to grab targets that we aren't // actively attacking change this to use that instead. @@ -5645,23 +5665,23 @@ bool mattack::grenadier( monster *const z ) bool mattack::grenadier_elite( monster *const z ) { // Build our grenade map - std::map grenades; + std::map grenades; // Grenades - grenades["bot_grenade_hack"].message = _( "The %s deploys a grenade hack!" ); + grenades[itype_bot_grenade_hack].message = _( "The %s deploys a grenade hack!" ); // Flashbangs - grenades["bot_flashbang_hack"].message = + grenades[itype_bot_flashbang_hack].message = _( "The %s deploys a flashbang hack!" ); // Gasbombs - grenades["bot_gasbomb_hack"].message = _( "The %s deploys a tear gas hack!" ); + grenades[itype_bot_gasbomb_hack].message = _( "The %s deploys a tear gas hack!" ); // C-4 - grenades["bot_c4_hack"].message = _( "The %s buzzes and deploys a C-4 hack!" ); - grenades["bot_c4_hack"].chance = 8; - grenades["bot_c4_hack"].ammo_percentage = .75; + grenades[itype_bot_c4_hack].message = _( "The %s buzzes and deploys a C-4 hack!" ); + grenades[itype_bot_c4_hack].chance = 8; + grenades[itype_bot_c4_hack].ammo_percentage = .75; // Mininuke - grenades["bot_mininuke_hack"].message = + grenades[itype_bot_mininuke_hack].message = _( "A klaxon blares from %s as it deploys a mininuke hack!" ); - grenades["bot_mininuke_hack"].chance = 50; - grenades["bot_mininuke_hack"].ammo_percentage = .75; + grenades[itype_bot_mininuke_hack].chance = 50; + grenades[itype_bot_mininuke_hack].ammo_percentage = .75; // Only can actively target the player right now. Once we have the ability to grab targets that we aren't // actively attacking change this to use that instead. diff --git a/src/mondeath.cpp b/src/mondeath.cpp index 3e0d87a9d6c96..17039319eb8f9 100644 --- a/src/mondeath.cpp +++ b/src/mondeath.cpp @@ -61,6 +61,9 @@ static const efftype_id effect_no_ammo( "no_ammo" ); static const efftype_id effect_pacified( "pacified" ); static const efftype_id effect_rat( "rat" ); +static const itype_id itype_processor( "processor" ); +static const itype_id itype_ruined_chunks( "ruined_chunks" ); + static const species_id species_BLOB( "BLOB" ); static const species_id ZOMBIE( "ZOMBIE" ); @@ -119,7 +122,7 @@ void mdeath::normal( monster &z ) } } -static void scatter_chunks( const std::string &chunk_name, int chunk_amt, monster &z, int distance, +static void scatter_chunks( const itype_id &chunk_name, int chunk_amt, monster &z, int distance, int pile_size = 1 ) { // can't have less than one item in a pile or it would cause an infinite loop @@ -207,15 +210,18 @@ void mdeath::splatter( monster &z ) // only flesh and bones survive. if( entry.type == "flesh" || entry.type == "bone" ) { // the larger the overflow damage, the less you get - const int chunk_amt = entry.mass_ratio / overflow_ratio / 10 * to_gram( - z.get_weight() ) / to_gram( ( item::find_type( entry.drop ) )->weight ); - scatter_chunks( entry.drop, chunk_amt, z, gib_distance, chunk_amt / ( gib_distance - 1 ) ); + const int chunk_amt = + entry.mass_ratio / overflow_ratio / 10 * + z.get_weight() / ( item::find_type( itype_id( entry.drop ) ) )->weight; + scatter_chunks( itype_id( entry.drop ), chunk_amt, z, gib_distance, + chunk_amt / ( gib_distance - 1 ) ); gibbed_weight -= entry.mass_ratio / overflow_ratio / 20 * to_gram( z.get_weight() ); } } if( gibbed_weight > 0 ) { - const int chunk_amount = gibbed_weight / to_gram( ( item::find_type( "ruined_chunks" ) )->weight ); - scatter_chunks( "ruined_chunks", chunk_amount, z, gib_distance, + const int chunk_amount = + gibbed_weight / to_gram( ( item::find_type( itype_ruined_chunks ) )->weight ); + scatter_chunks( itype_ruined_chunks, chunk_amount, z, gib_distance, chunk_amount / ( gib_distance + 1 ) ); } // add corpse with gib flag @@ -579,7 +585,7 @@ void mdeath::focused_beam( monster &z ) { map_stack items = g->m.i_at( z.pos() ); for( map_stack::iterator it = items.begin(); it != items.end(); ) { - if( it->typeId() == "processor" ) { + if( it->typeId() == itype_processor ) { it = items.erase( it ); } else { ++it; @@ -633,7 +639,7 @@ void mdeath::broken( monster &z ) g->m.add_item_or_charges( z.pos(), broken_mon ); if( z.type->has_flag( MF_DROPS_AMMO ) ) { - for( const std::pair &ammo_entry : z.type->starting_ammo ) { + for( const std::pair &ammo_entry : z.type->starting_ammo ) { if( z.ammo[ammo_entry.first] > 0 ) { bool spawned = false; for( const std::pair &attack : z.type->special_attacks ) { diff --git a/src/monexamine.cpp b/src/monexamine.cpp index 274dd9a5f65aa..af8a41a599d00 100644 --- a/src/monexamine.cpp +++ b/src/monexamine.cpp @@ -56,6 +56,9 @@ static const efftype_id effect_ridden( "ridden" ); static const efftype_id effect_saddled( "monster_saddled" ); static const efftype_id effect_tied( "tied" ); +static const itype_id itype_cash_card( "cash_card" ); +static const itype_id itype_id_military( "id_military" ); + static const skill_id skill_survival( "survival" ); static const species_id ZOMBIE( "ZOMBIE" ); @@ -357,7 +360,7 @@ void monexamine::insert_battery( monster &z ) bool monexamine::mech_hack( monster &z ) { - itype_id card_type = "id_military"; + itype_id card_type = itype_id_military; if( g->u.has_amount( card_type, 1 ) ) { if( query_yn( _( "Swipe your ID card into the mech's security port?" ) ) ) { g->u.mod_moves( -100 ); @@ -390,7 +393,7 @@ static int prompt_for_amount( const char *const msg, const int max ) bool monexamine::pay_bot( monster &z ) { time_duration friend_time = z.get_effect_dur( effect_pet ); - const int charge_count = g->u.charges_of( "cash_card" ); + const int charge_count = g->u.charges_of( itype_cash_card ); int amount = 0; uilist bot_menu; @@ -411,7 +414,7 @@ bool monexamine::pay_bot( monster &z ) "How much friendship do you get? Max: %d minutes.", charge_count / 10 ), charge_count / 10 ); if( amount > 0 ) { time_duration time_bought = time_duration::from_minutes( amount ); - g->u.use_charges( "cash_card", amount * 10 ); + g->u.use_charges( itype_cash_card, amount * 10 ); z.add_effect( effect_pet, time_bought ); z.add_effect( effect_paid, time_bought, num_bp, true ); z.friendly = -1; @@ -721,10 +724,10 @@ void monexamine::tie_or_untie( monster &z ) void monexamine::milk_source( monster &source_mon ) { - std::string milked_item = source_mon.type->starting_ammo.begin()->first; + itype_id milked_item = source_mon.type->starting_ammo.begin()->first; auto milkable_ammo = source_mon.ammo.find( milked_item ); if( milkable_ammo == source_mon.ammo.end() ) { - debugmsg( "The %s has no milkable %s.", source_mon.get_name(), milked_item ); + debugmsg( "The %s has no milkable %s.", source_mon.get_name(), milked_item.str() ); return; } if( milkable_ammo->second > 0 ) { diff --git a/src/monmove.cpp b/src/monmove.cpp index 25df312439527..9e45b6267907d 100644 --- a/src/monmove.cpp +++ b/src/monmove.cpp @@ -61,6 +61,8 @@ static const efftype_id effect_pacified( "pacified" ); static const efftype_id effect_pushed( "pushed" ); static const efftype_id effect_stunned( "stunned" ); +static const itype_id itype_pressurized_tank( "pressurized_tank" ); + static const species_id FUNGUS( "FUNGUS" ); static const species_id INSECT( "INSECT" ); static const species_id SPIDER( "SPIDER" ); @@ -1624,9 +1626,9 @@ bool monster::move_to( const tripoint &p, bool force, bool step_on_critter, if( has_flag( MF_DRIPS_NAPALM ) ) { if( one_in( 10 ) ) { // if it has more napalm, drop some and reduce ammo in tank - if( ammo["pressurized_tank"] > 0 ) { + if( ammo[itype_pressurized_tank] > 0 ) { g->m.add_item_or_charges( pos(), item( "napalm", calendar::turn, 50 ) ); - ammo["pressurized_tank"] -= 50; + ammo[itype_pressurized_tank] -= 50; } else { // TODO: remove MF_DRIPS_NAPALM flag since no more napalm in tank // Not possible for now since flag check is done on type, not individual monster diff --git a/src/monster.cpp b/src/monster.cpp index aa1a0697fd405..1ef479bd10c6e 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -85,6 +85,10 @@ static const efftype_id effect_supercharged( "supercharged" ); static const efftype_id effect_tied( "tied" ); static const efftype_id effect_webbed( "webbed" ); +static const itype_id itype_corpse( "corpse" ); +static const itype_id itype_milk( "milk" ); +static const itype_id itype_milk_raw( "milk_raw" ); + static const species_id FISH( "FISH" ); static const species_id FUNGUS( "FUNGUS" ); static const species_id INSECT( "INSECT" ); @@ -481,12 +485,12 @@ void monster::refill_udders() // legacy animals got empty ammo map, fill them up now if needed. ammo[type->starting_ammo.begin()->first] = type->starting_ammo.begin()->second; } - auto current_milk = ammo.find( "milk_raw" ); + auto current_milk = ammo.find( itype_milk_raw ); if( current_milk == ammo.end() ) { - current_milk = ammo.find( "milk" ); + current_milk = ammo.find( itype_milk ); if( current_milk != ammo.end() ) { // take this opportunity to update milk udders to raw_milk - ammo["milk_raw"] = current_milk->second; + ammo[itype_milk_raw] = current_milk->second; // Erase old key-value from map ammo.erase( current_milk ); } @@ -2746,7 +2750,7 @@ bool monster::is_dead() const void monster::init_from_item( const item &itm ) { - if( itm.typeId() == "corpse" ) { + if( itm.typeId() == itype_corpse ) { set_speed_base( get_speed_base() * 0.8 ); const int burnt_penalty = itm.burnt; hp = static_cast( hp * 0.7 ); @@ -2776,7 +2780,7 @@ void monster::init_from_item( const item &itm ) item monster::to_item() const { - if( type->revert_to_itype.empty() ) { + if( type->revert_to_itype.is_empty() ) { return item(); } // Birthday is wrong, but the item created here does not use it anyway (I hope). diff --git a/src/monster.h b/src/monster.h index 406d68431c723..1ee92bbb9822c 100644 --- a/src/monster.h +++ b/src/monster.h @@ -500,7 +500,7 @@ class monster : public Creature int staircount; // Ammunition if we use a gun. - std::map ammo; + std::map ammo; /** * Convert this monster into an item (see @ref mtype::revert_to_itype). diff --git a/src/monstergenerator.cpp b/src/monstergenerator.cpp index bddd553a75af6..eeff00b4ce5b1 100644 --- a/src/monstergenerator.cpp +++ b/src/monstergenerator.cpp @@ -742,11 +742,11 @@ void mtype::load( const JsonObject &jo, const std::string &src ) optional( jo, was_loaded, "starting_ammo", starting_ammo ); optional( jo, was_loaded, "luminance", luminance, 0 ); - optional( jo, was_loaded, "revert_to_itype", revert_to_itype, "" ); + optional( jo, was_loaded, "revert_to_itype", revert_to_itype, itype_id() ); optional( jo, was_loaded, "attack_effs", atk_effs, mon_attack_effect_reader{} ); - optional( jo, was_loaded, "mech_weapon", mech_weapon, "" ); + optional( jo, was_loaded, "mech_weapon", mech_weapon, itype_id() ); optional( jo, was_loaded, "mech_str_bonus", mech_str_bonus, 0 ); - optional( jo, was_loaded, "mech_battery", mech_battery, "" ); + optional( jo, was_loaded, "mech_battery", mech_battery, itype_id() ); // TODO: make this work with `was_loaded` if( jo.has_array( "melee_damage" ) ) { @@ -863,7 +863,7 @@ void mtype::load( const JsonObject &jo, const std::string &src ) optional( repro, was_loaded, "baby_monster", baby_monster, auto_flags_reader {}, mtype_id::NULL_ID() ); optional( repro, was_loaded, "baby_egg", baby_egg, auto_flags_reader {}, - "null" ); + itype_id::NULL_ID() ); reproduces = true; } @@ -885,7 +885,7 @@ void mtype::load( const JsonObject &jo, const std::string &src ) } optional( biosig, was_loaded, "biosig_item", biosig_item, auto_flags_reader {}, - "null" ); + itype_id::NULL_ID() ); biosignatures = true; } @@ -1146,9 +1146,9 @@ void MonsterGenerator::check_monster_definitions() const debugmsg( "monster %s is flagged milkable, but has no starting ammo", mon.id.c_str() ); } if( mon.has_flag( MF_MILKABLE ) && !mon.starting_ammo.empty() && - !item( itype_id( mon.starting_ammo.begin()->first ) ).made_of( LIQUID ) ) { + !item( mon.starting_ammo.begin()->first ).made_of( LIQUID ) ) { debugmsg( "monster % is flagged milkable, but starting ammo %s is not a liquid type", - mon.id.c_str(), mon.starting_ammo.begin()->first ); + mon.id.c_str(), mon.starting_ammo.begin()->first.str() ); } if( mon.has_flag( MF_MILKABLE ) && mon.starting_ammo.size() > 1 ) { debugmsg( "monster % is flagged milkable, but has multiple starting_ammo defined", mon.id.c_str() ); @@ -1167,15 +1167,15 @@ void MonsterGenerator::check_monster_definitions() const debugmsg( "monster %s has unknown material: %s", mon.id.c_str(), m.c_str() ); } } - if( !mon.revert_to_itype.empty() && !item::type_is_defined( mon.revert_to_itype ) ) { + if( !mon.revert_to_itype.is_empty() && !item::type_is_defined( mon.revert_to_itype ) ) { debugmsg( "monster %s has unknown revert_to_itype: %s", mon.id.c_str(), mon.revert_to_itype.c_str() ); } - if( !mon.mech_weapon.empty() && !item::type_is_defined( mon.mech_weapon ) ) { + if( !mon.mech_weapon.is_empty() && !item::type_is_defined( mon.mech_weapon ) ) { debugmsg( "monster %s has unknown mech_weapon: %s", mon.id.c_str(), mon.mech_weapon.c_str() ); } - if( !mon.mech_battery.empty() && !item::type_is_defined( mon.mech_battery ) ) { + if( !mon.mech_battery.is_empty() && !item::type_is_defined( mon.mech_battery ) ) { debugmsg( "monster %s has unknown mech_battery: %s", mon.id.c_str(), mon.mech_battery.c_str() ); } @@ -1237,10 +1237,10 @@ void MonsterGenerator::check_monster_definitions() const debugmsg( "Number of children (%d) is invalid for %s", mon.baby_count, mon.id.c_str() ); } - if( !mon.baby_monster && mon.baby_egg == "null" ) { + if( !mon.baby_monster && mon.baby_egg.is_null() ) { debugmsg( "No baby or egg defined for monster %s", mon.id.c_str() ); } - if( mon.baby_monster && mon.baby_egg != "null" ) { + if( mon.baby_monster && !mon.baby_egg.is_null() ) { debugmsg( "Both an egg and a live birth baby are defined for %s", mon.id.c_str() ); } if( !mon.baby_monster.is_valid() ) { @@ -1258,7 +1258,7 @@ void MonsterGenerator::check_monster_definitions() const debugmsg( "Time between biosignature drops (%d) is invalid for %s", mon.biosig_timer ? to_turns( *mon.biosig_timer ) : -1, mon.id.c_str() ); } - if( mon.biosig_item == "null" ) { + if( mon.biosig_item.is_null() ) { debugmsg( "No biosignature drop defined for monster %s", mon.id.c_str() ); } if( !item::type_is_defined( mon.biosig_item ) ) { diff --git a/src/morale.h b/src/morale.h index 1a4300731638b..37d91fe1ad615 100644 --- a/src/morale.h +++ b/src/morale.h @@ -199,7 +199,7 @@ class player_morale }; std::map mutations; - std::map super_fancy_items; + std::map super_fancy_items; // Mutability is required for lazy initialization mutable int level; diff --git a/src/mtype.cpp b/src/mtype.cpp index b5f102d6f8fa2..7f17dfb303382 100644 --- a/src/mtype.cpp +++ b/src/mtype.cpp @@ -12,6 +12,15 @@ #include "monstergenerator.h" #include "translations.h" +static const itype_id itype_bone( "bone" ); +static const itype_id itype_bone_tainted( "bone_tainted" ); +static const itype_id itype_fish( "fish" ); +static const itype_id itype_human_flesh( "human_flesh" ); +static const itype_id itype_meat( "meat" ); +static const itype_id itype_meat_tainted( "meat_tainted" ); +static const itype_id itype_veggy( "veggy" ); +static const itype_id itype_veggy_tainted( "veggy_tainted" ); + static const species_id MOLLUSK( "MOLLUSK" ); mtype::mtype() @@ -35,10 +44,10 @@ mtype::mtype() reproduces = false; baby_count = -1; baby_monster = mtype_id::NULL_ID(); - baby_egg = "null"; + baby_egg = itype_id::NULL_ID(); biosignatures = false; - biosig_item = "null"; + biosig_item = itype_id::NULL_ID(); burn_into = mtype_id::NULL_ID(); dies.push_back( &mdeath::normal ); @@ -187,34 +196,34 @@ itype_id mtype::get_meat_itype() const { if( has_flag( MF_POISON ) ) { if( made_of( material_id( "flesh" ) ) || made_of( material_id( "hflesh" ) ) ) { - return "meat_tainted"; + return itype_meat_tainted; } else if( made_of( material_id( "iflesh" ) ) ) { //In the future, insects could drop insect flesh rather than plain ol' meat. - return "meat_tainted"; + return itype_meat_tainted; } else if( made_of( material_id( "veggy" ) ) ) { - return "veggy_tainted"; + return itype_veggy_tainted; } else if( made_of( material_id( "bone" ) ) ) { - return "bone_tainted"; + return itype_bone_tainted; } } else { if( made_of( material_id( "flesh" ) ) || made_of( material_id( "hflesh" ) ) ) { if( has_flag( MF_HUMAN ) ) { - return "human_flesh"; + return itype_human_flesh; } else if( has_flag( MF_AQUATIC ) ) { - return "fish"; + return itype_fish; } else { - return "meat"; + return itype_meat; } } else if( made_of( material_id( "iflesh" ) ) ) { //In the future, insects could drop insect flesh rather than plain ol' meat. - return "meat"; + return itype_meat; } else if( made_of( material_id( "veggy" ) ) ) { - return "veggy"; + return itype_veggy; } else if( made_of( material_id( "bone" ) ) ) { - return "bone"; + return itype_bone; } } - return "null"; + return itype_id::NULL_ID(); } int mtype::get_meat_chunks_count() const diff --git a/src/mtype.h b/src/mtype.h index c625972ab3845..0e869c39e56c8 100644 --- a/src/mtype.h +++ b/src/mtype.h @@ -36,8 +36,6 @@ using bodytype_id = std::string; class JsonArray; class JsonObject; -using itype_id = std::string; - // These are triggers which may affect the monster's anger or morale. // They are handled in monster::check_triggers(), in monster.cpp enum class mon_trigger { @@ -227,7 +225,7 @@ struct mtype { public: mtype_id id; - std::map starting_ammo; // Amount of ammo the monster spawns with. + std::map starting_ammo; // Amount of ammo the monster spawns with. // Name of item group that is used to create item dropped upon death, or empty. std::string death_drops; diff --git a/src/mutation.cpp b/src/mutation.cpp index 3e0013593feb2..042c2d4b41f58 100644 --- a/src/mutation.cpp +++ b/src/mutation.cpp @@ -617,13 +617,13 @@ void Character::activate_mutation( const trait_id &mut ) tdata.powered = false; } return; - } else if( !mdata.spawn_item.empty() ) { + } else if( !mdata.spawn_item.is_empty() ) { item tmpitem( mdata.spawn_item ); i_add_or_drop( tmpitem ); add_msg_if_player( mdata.spawn_item_message() ); tdata.powered = false; return; - } else if( !mdata.ranged_mutation.empty() ) { + } else if( !mdata.ranged_mutation.is_empty() ) { add_msg_if_player( mdata.ranged_mutation_message() ); g->refresh_all(); avatar_action::fire_ranged_mutation( g->u, g->m, item( mdata.ranged_mutation ) ); diff --git a/src/mutation.h b/src/mutation.h index 3c109220013d9..06852100506fe 100644 --- a/src/mutation.h +++ b/src/mutation.h @@ -28,8 +28,6 @@ class player; struct dream; template struct enum_traits; template class string_id; - -using itype_id = std::string; class JsonArray; extern std::vector dreams; diff --git a/src/npc.cpp b/src/npc.cpp index 0846ad82080ca..67317c3d5fd3c 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -91,6 +91,8 @@ static const efftype_id effect_pkill3( "pkill3" ); static const efftype_id effect_ridden( "ridden" ); static const efftype_id effect_riding( "riding" ); +static const itype_id itype_UPS_off( "UPS_off" ); + static const skill_id skill_archery( "archery" ); static const skill_id skill_barter( "barter" ); static const skill_id skill_bashing( "bashing" ); @@ -166,7 +168,7 @@ npc::npc() } standard_npc::standard_npc( const std::string &name, const tripoint &pos, - const std::vector &clothing, + const std::vector &clothing, int sk_lvl, int s_str, int s_dex, int s_int, int s_per ) { this->name = name; @@ -1470,8 +1472,8 @@ void npc::decide_needs() if( weapon.is_gun() ) { int ups_drain = weapon.get_gun_ups_drain(); if( ups_drain > 0 ) { - int ups_charges = charges_of( "UPS_off", ups_drain ) + - charges_of( "UPS_off", ups_drain ); + int ups_charges = charges_of( itype_UPS_off, ups_drain ) + + charges_of( itype_UPS_off, ups_drain ); needrank[need_ammo] = static_cast( ups_charges ) / ups_drain; } else { needrank[need_ammo] = get_ammo( ammotype( *weapon.type->gun->ammo.begin() ) ).size(); @@ -1664,7 +1666,7 @@ void npc::shop_restock() int shop_value = 75000; if( my_fac ) { shop_value = my_fac->wealth * 0.0075; - if( mission == NPC_MISSION_SHOPKEEP && !my_fac->currency.empty() ) { + if( mission == NPC_MISSION_SHOPKEEP && !my_fac->currency.is_empty() ) { item my_currency( my_fac->currency ); if( !my_currency.is_null() ) { my_currency.set_owner( *this ); @@ -2120,7 +2122,7 @@ void npc::npc_dismount() } remove_effect( effect_riding ); if( mounted_creature->has_flag( MF_RIDEABLE_MECH ) && - !mounted_creature->type->mech_weapon.empty() ) { + !mounted_creature->type->mech_weapon.is_empty() ) { remove_item( weapon ); } mounted_creature->remove_effect( effect_ridden ); diff --git a/src/npc.h b/src/npc.h index 5dc090f390169..64b63271cdf41 100644 --- a/src/npc.h +++ b/src/npc.h @@ -67,7 +67,7 @@ using drop_location = std::pair; using drop_locations = std::list; void parse_tags( std::string &phrase, const Character &u, const Character &me, - const itype_id &item_type = "null" ); + const itype_id &item_type = itype_id::NULL_ID() ); /* * Talk: Trust midlow->high, fear low->mid, need doesn't matter @@ -956,7 +956,7 @@ class npc : public player bool took_painkiller() const; void use_painkiller(); void activate_item( int item_index ); - bool has_identified( const std::string & ) const override { + bool has_identified( const itype_id & ) const override { return true; } bool has_artifact_with( const art_effect_passive ) const override { @@ -1403,7 +1403,7 @@ class standard_npc : public npc public: standard_npc( const std::string &name = "", const tripoint &pos = tripoint( HALF_MAPSIZE_X, HALF_MAPSIZE_Y, 0 ), - const std::vector &clothing = {}, + const std::vector &clothing = {}, int sk_lvl = 4, int s_str = 8, int s_dex = 8, int s_int = 8, int s_per = 8 ); }; diff --git a/src/npc_favor.h b/src/npc_favor.h index 5b953ba6ee3eb..3a38ed8f3e444 100644 --- a/src/npc_favor.h +++ b/src/npc_favor.h @@ -6,7 +6,6 @@ #include "type_id.h" -using itype_id = std::string; class JsonIn; class JsonOut; @@ -28,7 +27,7 @@ struct npc_favor { npc_favor() { type = FAVOR_NULL; value = 0; - item_id = "null"; + item_id = itype_id::NULL_ID(); skill = skill_id::NULL_ID(); } diff --git a/src/npcmove.cpp b/src/npcmove.cpp index 5d289cbdec3a0..cb701df7b3d3b 100644 --- a/src/npcmove.cpp +++ b/src/npcmove.cpp @@ -117,6 +117,17 @@ static const efftype_id effect_npc_run_away( "npc_run_away" ); static const efftype_id effect_onfire( "onfire" ); static const efftype_id effect_stunned( "stunned" ); +static const itype_id itype_battery( "battery" ); +static const itype_id itype_chem_ethanol( "chem_ethanol" ); +static const itype_id itype_chem_methanol( "chem_methanol" ); +static const itype_id itype_denat_alcohol( "denat_alcohol" ); +static const itype_id itype_inhaler( "inhaler" ); +static const itype_id itype_lsd( "lsd" ); +static const itype_id itype_smoxygen_tank( "smoxygen_tank" ); +static const itype_id itype_thorazine( "thorazine" ); +static const itype_id itype_oxygen_tank( "oxygen_tank" ); +static const itype_id itype_UPS( "UPS" ); + static constexpr float NPC_DANGER_VERY_LOW = 5.0f; static constexpr float NPC_DANGER_MAX = 150.0f; static constexpr float MAX_FLOAT = 5000000000.0f; @@ -744,9 +755,9 @@ void npc::move() action = method_of_fleeing(); } else if( has_effect( effect_npc_run_away ) ) { action = method_of_fleeing(); - } else if( has_effect( effect_asthma ) && ( has_charges( "inhaler", 1 ) || - has_charges( "oxygen_tank", 1 ) || - has_charges( "smoxygen_tank", 1 ) ) ) { + } else if( has_effect( effect_asthma ) && ( has_charges( itype_inhaler, 1 ) || + has_charges( itype_oxygen_tank, 1 ) || + has_charges( itype_smoxygen_tank, 1 ) ) ) { action = npc_heal; } else if( target != nullptr && ai_cache.danger > 0 ) { action = method_of_attack(); @@ -1299,7 +1310,7 @@ npc_action npc::method_of_attack() // if there's enough of a threat to be here, power up the combat CBMs activate_combat_cbms(); - int ups_charges = charges_of( "UPS" ); + int ups_charges = charges_of( itype_UPS ); // get any suitable modes excluding melee, any forbidden to NPCs and those without ammo // if we require a silent weapon inappropriate modes are also removed @@ -1651,12 +1662,15 @@ bool npc::recharge_cbm() return true; } else { const std::vector fuel_op = bid->fuel_opts; - const bool need_alcohol = std::find( fuel_op.begin(), fuel_op.end(), - "chem_ethanol" ) != fuel_op.end() || - std::find( fuel_op.begin(), fuel_op.end(), "chem_methanol" ) != fuel_op.end() || - std::find( fuel_op.begin(), fuel_op.end(), "denat_alcohol" ) != fuel_op.end(); - - if( std::find( fuel_op.begin(), fuel_op.end(), "battery" ) != fuel_op.end() ) { + const bool need_alcohol = + std::find( fuel_op.begin(), fuel_op.end(), itype_chem_ethanol ) != + fuel_op.end() || + std::find( fuel_op.begin(), fuel_op.end(), itype_chem_methanol ) != + fuel_op.end() || + std::find( fuel_op.begin(), fuel_op.end(), itype_denat_alcohol ) != + fuel_op.end(); + + if( std::find( fuel_op.begin(), fuel_op.end(), itype_battery ) != fuel_op.end() ) { complain_about( "need_batteries", 3_hours, "", false ); } else if( need_alcohol ) { complain_about( "need_booze", 3_hours, "", false ); @@ -2719,8 +2733,8 @@ void npc::see_item_say_smth( const itype_id &object, const std::string &smth ) void npc::find_item() { if( is_hallucination() ) { - see_item_say_smth( "thorazine", "" ); - see_item_say_smth( "lsd", "" ); + see_item_say_smth( itype_thorazine, "" ); + see_item_say_smth( itype_lsd, "" ); return; } @@ -3329,7 +3343,7 @@ bool npc::wield_better_weapon() item *best = &weapon; double best_value = -100.0; - const int ups_charges = charges_of( "UPS" ); + const int ups_charges = charges_of( itype_UPS ); const auto compare_weapon = [this, &best, &best_value, ups_charges, can_use_gun, use_silent]( const item & it ) { @@ -3377,12 +3391,12 @@ bool npc::wield_better_weapon() // Until then, the NPCs should reload the guns as a last resort if( best == &weapon ) { - add_msg( m_debug, "Wielded %s is best at %.1f, not switching", best->type->get_id(), + add_msg( m_debug, "Wielded %s is best at %.1f, not switching", best->type->get_id().str(), best_value ); return false; } - add_msg( m_debug, "Wielding %s at value %.1f", best->type->get_id(), best_value ); + add_msg( m_debug, "Wielding %s at value %.1f", best->type->get_id().str(), best_value ); wield( *best ); return true; @@ -3622,13 +3636,13 @@ void npc::heal_self() if( has_effect( effect_asthma ) ) { item &treatment = null_item_reference(); std::string iusage = "OXYGEN_BOTTLE"; - if( has_charges( "inhaler", 1 ) ) { - treatment = inv.find_item( inv.position_by_type( "inhaler" ) ); + if( has_charges( itype_inhaler, 1 ) ) { + treatment = inv.find_item( inv.position_by_type( itype_inhaler ) ); iusage = "INHALER"; - } else if( has_charges( "oxygen_tank", 1 ) ) { - treatment = inv.find_item( inv.position_by_type( "oxygen_tank" ) ); - } else if( has_charges( "smoxygen_tank", 1 ) ) { - treatment = inv.find_item( inv.position_by_type( "smoxygen_tank" ) ); + } else if( has_charges( itype_oxygen_tank, 1 ) ) { + treatment = inv.find_item( inv.position_by_type( itype_oxygen_tank ) ); + } else if( has_charges( itype_smoxygen_tank, 1 ) ) { + treatment = inv.find_item( inv.position_by_type( itype_smoxygen_tank ) ); } if( !treatment.is_null() ) { treatment.type->invoke( *this, treatment, pos(), iusage ); @@ -4481,7 +4495,7 @@ void npc::do_reload( const item &it ) if( g->u.sees( *this ) ) { add_msg( _( "%1$s reloads their %2$s." ), name, it.tname() ); - sfx::play_variant_sound( "reload", it.typeId(), sfx::get_heard_volume( pos() ), + sfx::play_variant_sound( "reload", it.typeId().str(), sfx::get_heard_volume( pos() ), sfx::get_heard_angle( pos() ) ); } diff --git a/src/npctalk.cpp b/src/npctalk.cpp index e454304be56bd..cfaeb8d765de8 100644 --- a/src/npctalk.cpp +++ b/src/npctalk.cpp @@ -899,7 +899,7 @@ void npc::talk_to_u( bool text_only, bool radio_contact ) std::string dialogue::dynamic_line( const talk_topic &the_topic ) const { - if( the_topic.item_type != "null" ) { + if( !the_topic.item_type.is_null() ) { cur_item = the_topic.item_type; } @@ -1226,7 +1226,7 @@ talk_response &dialogue::add_response( const std::string &text, const std::strin talk_response &dialogue::add_response( const std::string &text, const std::string &r, const itype_id &item_type, const bool first ) { - if( item_type == "null" ) { + if( item_type.is_null() ) { debugmsg( "explicitly specified null item" ); } @@ -1603,7 +1603,7 @@ void parse_tags( std::string &phrase, const Character &u, const Character &me, if( !me.weapon.is_gun() ) { phrase.replace( fa, l, _( "BADAMMO" ) ); } else { - phrase.replace( fa, l, me.weapon.ammo_current() ); + phrase.replace( fa, l, me.weapon.ammo_current()->nname( 1 ) ); } } else if( tag == "" ) { std::string activity_name; @@ -2042,7 +2042,7 @@ void talk_effect_fun_t::set_adjust_var( const JsonObject &jo, const std::string }; } -void talk_effect_fun_t::set_u_buy_item( const std::string &item_name, int cost, int count, +void talk_effect_fun_t::set_u_buy_item( const itype_id &item_name, int cost, int count, const std::string &container_name ) { function = [item_name, cost, count, container_name]( const dialogue & d ) { @@ -2080,11 +2080,11 @@ void talk_effect_fun_t::set_u_buy_item( const std::string &item_name, int cost, // Update structure used by mission descriptions. if( cost <= 0 ) { - likely_rewards.push_back( std::pair( count, item_name ) ); + likely_rewards.push_back( std::pair( count, item_name ) ); } } -void talk_effect_fun_t::set_u_sell_item( const std::string &item_name, int cost, int count ) +void talk_effect_fun_t::set_u_sell_item( const itype_id &item_name, int cost, int count ) { function = [item_name, cost, count]( const dialogue & d ) { npc &p = *d.beta; @@ -2117,10 +2117,11 @@ void talk_effect_fun_t::set_consume_item( const JsonObject &jo, const std::strin int count, bool is_npc ) { - const std::string &item_name = jo.get_string( member ); + itype_id item_name; + jo.read( member, item_name, true ); function = [is_npc, item_name, count]( const dialogue & d ) { // this is stupid, but I couldn't get the assignment to work - const auto consume_item = [&]( player & p, const std::string & item_name, int count ) { + const auto consume_item = [&]( player & p, const itype_id & item_name, int count ) { item old_item( item_name ); if( p.has_charges( item_name, count ) ) { p.use_charges( item_name, count ); @@ -2320,7 +2321,7 @@ void talk_effect_fun_t::set_bulk_trade_accept( bool is_trade, bool is_npc ) tmp.charges = seller_has; if( is_trade ) { int price = tmp.price( true ) * ( is_npc ? -1 : 1 ) + d.beta->op_of_u.owed; - if( d.beta->get_faction() && !d.beta->get_faction()->currency.empty() ) { + if( d.beta->get_faction() && !d.beta->get_faction()->currency.is_empty() ) { const itype_id &pay_in = d.beta->get_faction()->currency; item pay( pay_in ); if( d.beta->value( pay ) > 0 ) { @@ -2370,7 +2371,7 @@ void talk_effect_fun_t::set_add_mission( const std::string &mission_id ) }; } -const std::vector> &talk_effect_fun_t::get_likely_rewards() const +const std::vector> &talk_effect_fun_t::get_likely_rewards() const { return likely_rewards; } @@ -2566,10 +2567,12 @@ void talk_effect_t::parse_sub_effect( const JsonObject &jo ) container_name = jo.get_string( "container" ); } if( jo.has_string( "u_sell_item" ) ) { - const std::string &item_name = jo.get_string( "u_sell_item" ); + itype_id item_name; + jo.read( "u_sell_item", item_name, true ); subeffect_fun.set_u_sell_item( item_name, cost, count ); } else if( jo.has_string( "u_buy_item" ) ) { - const std::string &item_name = jo.get_string( "u_buy_item" ); + itype_id item_name; + jo.read( "u_buy_item", item_name, true ); subeffect_fun.set_u_buy_item( item_name, cost, count, container_name ); } else if( jo.has_string( "u_consume_item" ) ) { subeffect_fun.set_consume_item( jo, "u_consume_item", count ); @@ -3152,7 +3155,7 @@ bool json_talk_topic::gen_responses( dialogue &d ) const actor = dynamic_cast( d.beta ); } std::function filter = return_true; - for( const std::string &item_id : repeat.for_item ) { + for( const itype_id &item_id : repeat.for_item ) { if( actor->charges_of( item_id ) > 0 || actor->has_amount( item_id, 1 ) ) { switch_done |= repeat.response.gen_repeat_response( d, item_id, switch_done ); } @@ -3279,7 +3282,7 @@ static consumption_result try_consume( npc &p, item &it, std::string &reason ) } } else if( to_eat.is_medication() ) { - if( comest->tool != "null" ) { + if( !comest->tool.is_null() ) { bool has = p.has_amount( comest->tool, 1 ); if( item::count_by_charges( comest->tool ) ) { has = p.has_charges( comest->tool, 1 ); @@ -3345,9 +3348,9 @@ std::string give_item_to( npc &p, bool allow_use ) const double new_weapon_value = p.weapon_value( given, new_ammo ); const double cur_weapon_value = p.weapon_value( p.weapon, our_ammo ); add_msg( m_debug, "NPC evaluates own %s (%d ammo): %0.1f", - p.weapon.typeId(), our_ammo, cur_weapon_value ); + p.weapon.typeId().str(), our_ammo, cur_weapon_value ); add_msg( m_debug, "NPC evaluates your %s (%d ammo): %0.1f", - given.typeId(), new_ammo, new_weapon_value ); + given.typeId().str(), new_ammo, new_weapon_value ); if( allow_use ) { // Eating first, to avoid evaluating bread as a weapon const auto consume_res = try_consume( p, given, reason ); diff --git a/src/npctalk_funcs.cpp b/src/npctalk_funcs.cpp index dc473bdf840a6..73929c3d0d111 100644 --- a/src/npctalk_funcs.cpp +++ b/src/npctalk_funcs.cpp @@ -481,11 +481,12 @@ void talk_function::bionic_remove( npc &p ) std::vector bionic_types; std::vector bionic_names; for( const bionic &bio : all_bio ) { - if( std::find( bionic_types.begin(), bionic_types.end(), bio.id.str() ) == bionic_types.end() ) { + if( std::find( bionic_types.begin(), bionic_types.end(), + bio.info().itype() ) == bionic_types.end() ) { if( bio.id != bio_power_storage || bio.id != bio_power_storage_mkII ) { - bionic_types.push_back( bio.id.str() ); - if( item::type_is_defined( bio.id.str() ) ) { + bionic_types.push_back( bio.info().itype() ); + if( item::type_is_defined( bio.info().itype() ) ) { item tmp = item( bio.id.str(), 0 ); bionic_names.push_back( tmp.tname() + " - " + format_money( 50000 + ( tmp.price( true ) / 4 ) ) ); } else { @@ -514,9 +515,9 @@ void talk_function::bionic_remove( npc &p ) } //Makes the doctor awesome at installing but not perfect - if( g->u.can_uninstall_bionic( bionic_id( bionic_types[bionic_index] ), p, false ) ) { + if( g->u.can_uninstall_bionic( bionic_id( bionic_types[bionic_index].str() ), p, false ) ) { g->u.amount_of( bionic_types[bionic_index] ); // ??? this does nothing, it just queries the count - g->u.uninstall_bionic( bionic_id( bionic_types[bionic_index] ), p, false ); + g->u.uninstall_bionic( bionic_id( bionic_types[bionic_index].str() ), p, false ); } } diff --git a/src/pickup.cpp b/src/pickup.cpp index 1c25a75a1528b..7d7cb190160cb 100644 --- a/src/pickup.cpp +++ b/src/pickup.cpp @@ -57,6 +57,8 @@ using ItemCount = std::pair; using PickupMap = std::map; +static const itype_id itype_water( "water" ); + // Pickup helper functions static bool pick_one_up( item_location &loc, int quantity, bool &got_water, bool &offered_swap, PickupMap &mapPickup, bool autopickup ); @@ -449,7 +451,7 @@ void Pickup::pick_up( const tripoint &p, int min, from_where get_items_from ) if( ( !isEmpty ) && g->m.furn( p ) == f_toilet ) { isEmpty = true; for( const item &maybe_water : g->m.i_at( p ) ) { - if( maybe_water.typeId() != "water" || maybe_water.is_frozen_liquid() ) { + if( maybe_water.typeId() != itype_water || maybe_water.is_frozen_liquid() ) { isEmpty = false; break; } diff --git a/src/player.cpp b/src/player.cpp index 2b604a5e0bd80..49c39c65b5690 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -117,6 +117,17 @@ static const efftype_id effect_stunned( "stunned" ); static const efftype_id effect_tapeworm( "tapeworm" ); static const efftype_id effect_weed_high( "weed_high" ); +static const itype_id itype_adv_UPS_off( "adv_UPS_off" ); +static const itype_id itype_battery( "battery" ); +static const itype_id itype_brass_catcher( "brass_catcher" ); +static const itype_id itype_cookbook_human( "cookbook_human" ); +static const itype_id itype_large_repairkit( "large_repairkit" ); +static const itype_id itype_plut_cell( "plut_cell" ); +static const itype_id itype_small_repairkit( "small_repairkit" ); +static const itype_id itype_syringe( "syringe" ); +static const itype_id itype_UPS( "UPS" ); +static const itype_id itype_UPS_off( "UPS_off" ); + static const trait_id trait_ACIDBLOOD( "ACIDBLOOD" ); static const trait_id trait_ANTENNAE( "ANTENNAE" ); static const trait_id trait_DEBUG_NODMG( "DEBUG_NODMG" ); @@ -1839,9 +1850,9 @@ void player::process_items() for( size_t index = 0; index < inv.size(); index++ ) { item &it = inv.find_item( index ); itype_id identifier = it.type->get_id(); - if( identifier == "UPS_off" ) { + if( identifier == itype_UPS_off ) { ch_UPS += it.ammo_remaining(); - } else if( identifier == "adv_UPS_off" ) { + } else if( identifier == itype_adv_UPS_off ) { ch_UPS += it.ammo_remaining() / 0.6; } if( it.has_flag( "USE_UPS" ) && it.charges < it.type->maximum_charges() ) { @@ -1865,9 +1876,9 @@ void player::process_items() } // Necessary for UPS in Aftershock - check worn items for charge const itype_id &identifier = w.typeId(); - if( identifier == "UPS_off" ) { + if( identifier == itype_UPS_off ) { ch_UPS += w.ammo_remaining(); - } else if( identifier == "adv_UPS_off" ) { + } else if( identifier == itype_adv_UPS_off ) { ch_UPS += w.ammo_remaining() / 0.6; } if( !update_required && w.encumbrance_update_ ) { @@ -1884,13 +1895,13 @@ void player::process_items() int ch_UPS_used = 0; if( cloak != nullptr ) { if( ch_UPS >= 20 ) { - use_charges( "UPS", 20 ); + use_charges( itype_UPS, 20 ); ch_UPS -= 20; if( ch_UPS < 200 && one_in( 3 ) ) { add_msg_if_player( m_warning, _( "Your cloaking flickers for a moment!" ) ); } } else if( ch_UPS > 0 ) { - use_charges( "UPS", ch_UPS ); + use_charges( itype_UPS, ch_UPS ); return; } else { add_msg_if_player( m_bad, @@ -1908,7 +1919,7 @@ void player::process_items() // Bionic power costs are handled elsewhere. if( !bio_powered ) { if( ch_UPS >= power_cost ) { - use_charges( "UPS", power_cost ); + use_charges( itype_UPS, power_cost ); ch_UPS -= power_cost; } else { // Deactivate armor here, bypassing the usual deactivation message. @@ -1940,7 +1951,7 @@ void player::process_items() worn_item->charges++; } if( ch_UPS_used > 0 ) { - use_charges( "UPS", ch_UPS_used ); + use_charges( itype_UPS, ch_UPS_used ); } } @@ -2056,7 +2067,7 @@ item::reload_option player::select_ammo( const item &base, std::transform( opts.begin(), opts.end(), std::back_inserter( names ), [&]( const item::reload_option & e ) { if( e.ammo->is_magazine() && e.ammo->ammo_data() ) { - if( e.ammo->ammo_current() == "battery" ) { + if( e.ammo->ammo_current() == itype_battery ) { // This battery ammo is not a real object that can be recovered but pseudo-object that represents charge //~ battery storage (charges) return string_format( pgettext( "magazine", "%1$s (%2$d)" ), e.ammo->type_name(), @@ -2142,7 +2153,8 @@ item::reload_option player::select_ammo( const item &base, return row; }; - itype_id last = uistate.lastreload[ ammotype( base.ammo_default() ) ]; + const ammotype base_ammotype( base.ammo_default().str() ); + itype_id last = uistate.lastreload[ base_ammotype ]; // We keep the last key so that pressing the key twice (for example, r-r for reload) // will always pick the first option on the list. int last_key = inp_mngr.get_previously_pressed_key(); @@ -2250,10 +2262,10 @@ item::reload_option player::select_ammo( const item &base, } const item_location &sel = opts[ menu.ret ].ammo; - uistate.lastreload[ ammotype( base.ammo_default() ) ] = sel->is_ammo_container() ? - // get first item in all magazine pockets - sel->contents.first_ammo().typeId() : - sel->typeId(); + uistate.lastreload[ base_ammotype ] = sel->is_ammo_container() ? + // get first item in all magazine pockets + sel->contents.first_ammo().typeId() : + sel->typeId(); return opts[ menu.ret ]; } @@ -2573,7 +2585,7 @@ void player::mend_item( item_location &&obj, bool interactive ) if( interactive ) { add_msg( m_info, _( "The %s doesn't have any faults to mend." ), obj->tname() ); if( obj->damage() > 0 ) { - const std::set &rep = obj->repaired_with(); + const std::set &rep = obj->repaired_with(); if( !rep.empty() ) { const std::string repair_options = enumerate_as_string( rep.begin(), rep.end(), []( const itype_id & e ) { @@ -3010,7 +3022,7 @@ bool player::unload( item_location &loc ) } else if( target->ammo_remaining() ) { int qty = target->ammo_remaining(); - if( target->ammo_current() == "plut_cell" ) { + if( target->ammo_current() == itype_plut_cell ) { if( qty / PLUTONIUM_CHARGES > 0 ) { add_msg( _( "You recover %i unused plutonium." ), qty / PLUTONIUM_CHARGES ); } else { @@ -3277,7 +3289,7 @@ bool player::gunmod_remove( item &gun, item &mod ) gun.gun_set_mode( gun_mode_id( "DEFAULT" ) ); //TODO: add activity for removing gunmods - if( mod.typeId() == "brass_catcher" ) { + if( mod.typeId() == itype_brass_catcher ) { gun.casings_handle( [&]( item & e ) { return i_add_or_drop( e ); } ); @@ -3392,7 +3404,7 @@ void player::gunmod_add( item &gun, item &mod ) string_format( _( "Try without tools (%i%%) risking damage (%i%%)" ), roll, risk ) ); actions.emplace_back( [&] {} ); - prompt.addentry( -1, has_charges( "small_repairkit", 100 ), 'f', + prompt.addentry( -1, has_charges( itype_small_repairkit, 100 ), 'f', string_format( _( "Use 100 charges of firearm repair kit (%i%%)" ), std::min( roll * 2, 100 ) ) ); actions.emplace_back( [&] { @@ -3402,7 +3414,7 @@ void player::gunmod_add( item &gun, item &mod ) risk /= 2; // ...and reduces the risk of damage upon failure } ); - prompt.addentry( -1, has_charges( "large_repairkit", 25 ), 'g', + prompt.addentry( -1, has_charges( itype_large_repairkit, 25 ), 'g', string_format( _( "Use 25 charges of gunsmith repair kit (%i%%)" ), std::min( roll * 3, 100 ) ) ); actions.emplace_back( [&] { @@ -3459,7 +3471,7 @@ bool player::fun_to_read( const item &book ) const // If you don't have a problem with eating humans, To Serve Man becomes rewarding if( ( has_trait( trait_CANNIBAL ) || has_trait( trait_PSYCHOPATH ) || has_trait( trait_SAPIOVORE ) ) && - book.typeId() == "cookbook_human" ) { + book.typeId() == itype_cookbook_human ) { return true; } else if( has_trait( trait_SPIRITUAL ) && book.has_flag( "INSPIRATIONAL" ) ) { return true; @@ -3479,7 +3491,7 @@ int player::book_fun_for( const item &book, const player &p ) const // If you don't have a problem with eating humans, To Serve Man becomes rewarding if( ( p.has_trait( trait_CANNIBAL ) || p.has_trait( trait_PSYCHOPATH ) || p.has_trait( trait_SAPIOVORE ) ) && - book.typeId() == "cookbook_human" ) { + book.typeId() == itype_cookbook_human ) { fun_bonus = std::abs( fun_bonus ); } else if( p.has_trait( trait_SPIRITUAL ) && book.has_flag( "INSPIRATIONAL" ) ) { fun_bonus = std::abs( fun_bonus * 3 ); diff --git a/src/player.h b/src/player.h index e37f8bc2afe1c..0663b05375794 100644 --- a/src/player.h +++ b/src/player.h @@ -63,9 +63,6 @@ class JsonOut; class dispersion_sources; struct bionic; struct dealt_projectile_attack; - -using itype_id = std::string; -using faction_id = string_id; class profession; struct trap; @@ -396,7 +393,7 @@ class player : public Character * @note items currently loaded with a detachable magazine are considered reloadable * @note items with integral magazines are reloadable if free capacity permits (+/- ammo matches) */ - bool can_reload( const item &it, const itype_id &ammo = std::string() ) const; + bool can_reload( const item &it, const itype_id &ammo = itype_id() ) const; /** * Attempt to mend an item (fix any current faults) @@ -476,7 +473,7 @@ class player : public Character bool fun_to_read( const item &book ) const; /** Note that we've read a book at least once. **/ - virtual bool has_identified( const std::string &item_id ) const = 0; + virtual bool has_identified( const itype_id &item_id ) const = 0; /** Handles sleep attempts by the player, starts ACT_TRY_SLEEP activity */ void try_to_sleep( const time_duration &dur = 30_minutes ); diff --git a/src/profession.cpp b/src/profession.cpp index 9892806376979..34ea7b3a75d98 100644 --- a/src/profession.cpp +++ b/src/profession.cpp @@ -139,7 +139,7 @@ class item_reader : public generic_typed_reader void erase_next( JsonIn &jin, C &container ) const { const std::string id = jin.get_string(); reader_detail::handler().erase_if( container, [&id]( const profession::itypedec & e ) { - return e.type_id == id; + return e.type_id.str() == id; } ); } }; @@ -256,15 +256,16 @@ void profession::check_item_definitions( const itypedecvec &items ) const { for( auto &itd : items ) { if( !item::type_is_defined( itd.type_id ) ) { - debugmsg( "profession %s: item %s does not exist", id.str(), itd.type_id ); + debugmsg( "profession %s: item %s does not exist", id.str(), itd.type_id.str() ); } else if( !itd.snip_id.is_null() ) { const itype *type = item::find_type( itd.type_id ); if( type->snippet_category.empty() ) { - debugmsg( "profession %s: item %s has no snippet category - no description can be set", - id.str(), itd.type_id ); + debugmsg( "profession %s: item %s has no snippet category - no description can " + "be set", id.str(), itd.type_id.str() ); } else { if( !itd.snip_id.is_valid() ) { - debugmsg( "profession %s: there's no snippet with id %s", id.str(), itd.snip_id.str() ); + debugmsg( "profession %s: there's no snippet with id %s", + id.str(), itd.snip_id.str() ); } } } @@ -276,7 +277,7 @@ void profession::check_definition() const check_item_definitions( legacy_starting_items ); check_item_definitions( legacy_starting_items_female ); check_item_definitions( legacy_starting_items_male ); - if( !no_bonus.empty() && !item::type_is_defined( no_bonus ) ) { + if( !no_bonus.is_empty() && !item::type_is_defined( no_bonus ) ) { debugmsg( "no_bonus item '%s' is not an itype_id", no_bonus.c_str() ); } @@ -530,10 +531,10 @@ void json_item_substitution::reset() json_item_substitution::substitution::info::info( const JsonValue &value ) { if( value.test_string() ) { - new_item = value.get_string(); + value.read( new_item, true ); } else { const JsonObject jo = value.get_object(); - new_item = jo.get_string( "item" ); + jo.read( "item", new_item, true ); ratio = jo.get_float( "ratio" ); if( ratio <= 0.0 ) { jo.throw_error( "Ratio must be positive", "ratio" ); @@ -563,13 +564,14 @@ void json_item_substitution::load( const JsonObject &jo ) return p.first == it; } ) != bonuses.end(); }; - if( item_mode && check_duplicate_item( title ) ) { + if( item_mode && check_duplicate_item( itype_id( title ) ) ) { jo.throw_error( "Duplicate definition of item" ); } if( item_mode ) { if( jo.has_member( "bonus" ) ) { - bonuses.emplace_back( title, trait_requirements( jo.get_object( "bonus" ) ) ); + bonuses.emplace_back( itype_id( title ), + trait_requirements( jo.get_object( "bonus" ) ) ); } for( const JsonValue sub : jo.get_array( "sub" ) ) { @@ -579,12 +581,13 @@ void json_item_substitution::load( const JsonObject &jo ) for( const JsonValue info : obj.get_array( "new" ) ) { s.infos.emplace_back( info ); } - substitutions[title].push_back( s ); + substitutions[itype_id( title )].push_back( s ); } } else { for( const JsonObject sub : jo.get_array( "sub" ) ) { substitution s; - const itype_id old_it = sub.get_string( "item" ); + itype_id old_it; + sub.read( "item", old_it, true ); if( check_duplicate_item( old_it ) ) { sub.throw_error( "Duplicate definition of item" ); } diff --git a/src/profession.h b/src/profession.h index f3f7ccc812242..94e9c7cf01a23 100644 --- a/src/profession.h +++ b/src/profession.h @@ -20,8 +20,6 @@ class generic_factory; using Group_tag = std::string; class item; - -using itype_id = std::string; class JsonObject; class avatar; class player; @@ -32,7 +30,7 @@ class profession using StartingSkill = std::pair; using StartingSkillList = std::vector; struct itypedec { - std::string type_id; + itype_id type_id; /** Snippet id, @see snippet_library. */ snippet_id snip_id; // compatible with when this was just a std::string diff --git a/src/ranged.cpp b/src/ranged.cpp index 96630861b1659..331fa248b19dd 100644 --- a/src/ranged.cpp +++ b/src/ranged.cpp @@ -73,6 +73,19 @@ static const efftype_id effect_downed( "downed" ); static const efftype_id effect_hit_by_player( "hit_by_player" ); static const efftype_id effect_on_roof( "on_roof" ); +static const itype_id itype_12mm( "12mm" ); +static const itype_id itype_40x46mm( "40x46mm" ); +static const itype_id itype_40x53mm( "40x53mm" ); +static const itype_id itype_66mm( "66mm" ); +static const itype_id itype_84x246mm( "84x246mm" ); +static const itype_id itype_arrow( "arrow" ); +static const itype_id itype_bolt( "bolt" ); +static const itype_id itype_brass_catcher( "brass_catcher" ); +static const itype_id itype_flammable( "flammable" ); +static const itype_id itype_m235( "m235" ); +static const itype_id itype_metal_rail( "metal_rail" ); +static const itype_id itype_UPS( "UPS" ); + static const trap_str_id tr_practice_target( "tr_practice_target" ); static const fault_id fault_gun_blackpowder( "fault_gun_blackpowder" ); @@ -762,7 +775,7 @@ int player::fire_gun( const tripoint &target, int shots, item &gun ) // cap our maximum burst size by the amount of UPS power left if( !gun.has_flag( flag_VEHICLE ) && gun.get_gun_ups_drain() > 0 ) { - shots = std::min( shots, static_cast( charges_of( "UPS" ) / gun.get_gun_ups_drain() ) ); + shots = std::min( shots, static_cast( charges_of( itype_UPS ) / gun.get_gun_ups_drain() ) ); } if( shots <= 0 ) { @@ -820,8 +833,8 @@ int player::fire_gun( const tripoint &target, int shots, item &gun ) cycle_action( gun, pos() ); if( has_trait( trait_PYROMANIA ) && !has_morale( MORALE_PYROMANIA_STARTFIRE ) ) { - if( gun.ammo_current() == "flammable" || gun.ammo_current() == "66mm" || - gun.ammo_current() == "84x246mm" || gun.ammo_current() == "m235" ) { + if( gun.ammo_current() == itype_flammable || gun.ammo_current() == itype_66mm || + gun.ammo_current() == itype_84x246mm || gun.ammo_current() == itype_m235 ) { add_msg_if_player( m_good, _( "You feel a surge of euphoria as flames roar out of the %s!" ), gun.tname() ); add_morale( MORALE_PYROMANIA_STARTFIRE, 15, 15, 8_hours, 6_hours ); @@ -835,7 +848,7 @@ int player::fire_gun( const tripoint &target, int shots, item &gun ) } if( !gun.has_flag( flag_VEHICLE ) ) { - use_charges( "UPS", gun.get_gun_ups_drain() ); + use_charges( itype_UPS, gun.get_gun_ups_drain() ); } if( shot.missed_by <= .1 ) { @@ -1549,7 +1562,7 @@ static projectile make_gun_projectile( const item &gun ) const auto &ammo = gun.ammo_data()->ammo; proj.critical_multiplier = ammo->critical_multiplier; - if( ammo->drop != "null" && x_in_y( ammo->drop_chance, 1.0 ) ) { + if( !ammo->drop.is_null() && x_in_y( ammo->drop_chance, 1.0 ) ) { item drop( ammo->drop ); if( ammo->drop_active ) { drop.activate(); @@ -1592,7 +1605,7 @@ static void cycle_action( item &weap, const tripoint &pos ) if( weap.ammo_data() && weap.ammo_data()->ammo->casing ) { const itype_id casing = *weap.ammo_data()->ammo->casing; - if( weap.has_flag( "RELOAD_EJECT" ) || weap.gunmod_find( "brass_catcher" ) ) { + if( weap.has_flag( "RELOAD_EJECT" ) || weap.gunmod_find( itype_brass_catcher ) ) { weap.put_in( item( casing ).set_flag( "CASING" ), item_pocket::pocket_type::CONTAINER ); } else { if( cargo.empty() ) { @@ -1610,7 +1623,7 @@ static void cycle_action( item &weap, const tripoint &pos ) const auto mag = weap.magazine_current(); if( mag && mag->type->magazine->linkage ) { item linkage( *mag->type->magazine->linkage, calendar::turn, 1 ); - if( weap.gunmod_find( "brass_catcher" ) ) { + if( weap.gunmod_find( itype_brass_catcher ) ) { linkage.set_flag( "CASING" ); weap.put_in( linkage, item_pocket::pocket_type::CONTAINER ); } else if( cargo.empty() ) { @@ -1646,21 +1659,21 @@ item::sound_data item::gun_noise( const bool burst ) const noise = std::max( noise, 0 ); - if( ammo_current() == "40x46mm" || ammo_current() == "40x53mm" ) { + if( ammo_current() == itype_40x46mm || ammo_current() == itype_40x53mm ) { // Grenade launchers return { 8, _( "Thunk!" ) }; - } else if( ammo_current() == "12mm" || ammo_current() == "metal_rail" ) { + } else if( ammo_current() == itype_12mm || ammo_current() == itype_metal_rail ) { // Railguns return { 24, _( "tz-CRACKck!" ) }; - } else if( ammo_current() == "flammable" || ammo_current() == "66mm" || - ammo_current() == "84x246mm" || ammo_current() == "m235" ) { + } else if( ammo_current() == itype_flammable || ammo_current() == itype_66mm || + ammo_current() == itype_84x246mm || ammo_current() == itype_m235 ) { // Rocket launchers and flamethrowers return { 4, _( "Fwoosh!" ) }; - } else if( ammo_current() == "arrow" ) { + } else if( ammo_current() == itype_arrow ) { return { noise, _( "whizz!" ) }; - } else if( ammo_current() == "bolt" ) { + } else if( ammo_current() == itype_bolt ) { return { noise, _( "thonk!" ) }; } @@ -1787,14 +1800,14 @@ double player::gun_value( const item &weap, int ammo ) const const islot_gun &gun = *weap.type->gun; itype_id ammo_type; - if( weap.ammo_current() != "null" ) { + if( !weap.ammo_current().is_null() ) { ammo_type = weap.ammo_current(); } else if( weap.magazine_current() ) { ammo_type = weap.common_ammo_default(); } else { ammo_type = weap.ammo_default(); } - const itype *def_ammo_i = ammo_type != "NULL" ? + const itype *def_ammo_i = !ammo_type.is_null() ? item::find_type( ammo_type ) : nullptr; @@ -1887,7 +1900,7 @@ double player::gun_value( const item &weap, int ammo ) const double gun_value = damage_and_accuracy * capacity_factor; add_msg( m_debug, "%s as gun: %.1f total, %.1f dispersion, %.1f damage, %.1f capacity", - weap.type->get_id(), gun_value, dispersion_factor, damage_factor, + weap.type->get_id().str(), gun_value, dispersion_factor, damage_factor, capacity_factor ); return std::max( 0.0, gun_value ); } @@ -2618,7 +2631,7 @@ void target_ui::action_switch_mode( player &pc ) } if( mode == TargetMode::TurretManual ) { itype_id ammo_current = turret->ammo_current(); - if( ammo_current == "null" ) { + if( ammo_current.is_null() ) { ammo = nullptr; range = 0; } else { diff --git a/src/recipe.cpp b/src/recipe.cpp index 8b6ae47100308..46d2f5c087c18 100644 --- a/src/recipe.cpp +++ b/src/recipe.cpp @@ -29,6 +29,8 @@ #include "units.h" #include "value_ptr.h" +static const itype_id itype_hotplate( "hotplate" ); + extern bool test_mode; recipe::recipe() : skill_used( skill_id::NULL_ID() ) {} @@ -96,8 +98,8 @@ void recipe::load( const JsonObject &jo, const std::string &src ) if( abstract ) { ident_ = recipe_id( jo.get_string( "abstract" ) ); } else { - result_ = jo.get_string( "result" ); - ident_ = recipe_id( result_ ); + jo.read( "result", result_, true ); + ident_ = recipe_id( result_.str() ); } if( jo.has_bool( "obsolete" ) ) { @@ -183,7 +185,8 @@ void recipe::load( const JsonObject &jo, const std::string &src ) if( jo.has_member( "book_learn" ) ) { booksets.clear(); for( JsonArray arr : jo.get_array( "book_learn" ) ) { - booksets.emplace( arr.get_string( 0 ), arr.size() > 1 ? arr.get_int( 1 ) : -1 ); + booksets.emplace( itype_id( arr.get_string( 0 ) ), + arr.size() > 1 ? arr.get_int( 1 ) : -1 ); } } @@ -233,7 +236,8 @@ void recipe::load( const JsonObject &jo, const std::string &src ) } byproducts.clear(); for( JsonArray arr : jo.get_array( "byproducts" ) ) { - byproducts[ arr.get_string( 0 ) ] += arr.size() == 2 ? arr.get_int( 1 ) : 1; + itype_id byproduct( arr.get_string( 0 ) ); + byproducts[ byproduct ] += arr.size() == 2 ? arr.get_int( 1 ) : 1; } } assign( jo, "construction_blueprint", blueprint ); @@ -248,13 +252,13 @@ void recipe::load( const JsonObject &jo, const std::string &src ) provide.get_int( "amount", 1 ) ) ); } // all blueprints provide themselves with needing it written in JSON - bp_provides.emplace_back( std::make_pair( result_, 1 ) ); + bp_provides.emplace_back( std::make_pair( result_.str(), 1 ) ); for( JsonObject require : jo.get_array( "blueprint_requires" ) ) { bp_requires.emplace_back( std::make_pair( require.get_string( "id" ), require.get_int( "amount", 1 ) ) ); } // all blueprints exclude themselves with needing it written in JSON - bp_excludes.emplace_back( std::make_pair( result_, 1 ) ); + bp_excludes.emplace_back( std::make_pair( result_.str(), 1 ) ); for( JsonObject exclude : jo.get_array( "blueprint_excludes" ) ) { bp_excludes.emplace_back( std::make_pair( exclude.get_string( "id" ), exclude.get_int( "amount", 1 ) ) ); @@ -326,7 +330,7 @@ void recipe::finalize() deduped_requirements_ = deduped_requirement_data( requirements_, ident() ); - if( contained && container == "null" ) { + if( contained && container.is_null() ) { container = item::find_type( result_ )->default_container.value_or( "null" ); } @@ -371,7 +375,7 @@ std::string recipe::get_consistency_error() const return "defines invalid byproducts"; } - if( !contained && container != "null" ) { + if( !contained && !container.is_null() ) { return "defines container but not contained"; } @@ -744,7 +748,7 @@ bool recipe::hot_result() const const requirement_data::alter_tool_comp_vector &tool_lists = simple_requirements().get_tools(); for( const std::vector &tools : tool_lists ) { for( const tool_comp &t : tools ) { - if( t.type == "hotplate" ) { + if( t.type == itype_hotplate ) { return true; } } diff --git a/src/recipe.h b/src/recipe.h index 58a219420a475..f112a2a094e91 100644 --- a/src/recipe.h +++ b/src/recipe.h @@ -18,8 +18,6 @@ class JsonObject; class item; class time_duration; - -using itype_id = std::string; // From itype.h class Character; enum class recipe_filter_flags : int { @@ -38,13 +36,13 @@ class recipe friend class recipe_dictionary; private: - itype_id result_ = "null"; + itype_id result_ = itype_id::NULL_ID(); public: recipe(); operator bool() const { - return result_ != "null"; + return !result_.is_null(); } const itype_id &result() const { @@ -197,7 +195,7 @@ class recipe bool reversible = false; /** What does the item spawn contained in? Unset ("null") means default container. */ - itype_id container = "null"; + itype_id container = itype_id::NULL_ID(); /** External requirements (via "using" syntax) where second field is multiplier */ std::vector> reqs_external; diff --git a/src/recipe_dictionary.cpp b/src/recipe_dictionary.cpp index c871bacc07f77..79fc04a551292 100644 --- a/src/recipe_dictionary.cpp +++ b/src/recipe_dictionary.cpp @@ -71,7 +71,7 @@ bool string_id::is_valid() const const recipe &recipe_dictionary::get_uncraft( const itype_id &id ) { - auto iter = recipe_dict.uncraft.find( recipe_id( id ) ); + auto iter = recipe_dict.uncraft.find( recipe_id( id.str() ) ); return iter != recipe_dict.uncraft.end() ? iter->second : null_recipe; } @@ -390,9 +390,9 @@ void recipe_dictionary::find_items_on_loops() std::vector> loops = cata::find_cycles( potential_components_of ); for( const std::vector &loop : loops ) { std::string error_message = - "loop in comestible recipes detected: " + loop.back(); + "loop in comestible recipes detected: " + loop.back().str(); for( const itype_id &i : loop ) { - error_message += " -> " + i; + error_message += " -> " + i.str(); items_on_loops.insert( i ); } error_message += ". Such loops can be broken by either removing or altering " @@ -429,15 +429,15 @@ void recipe_dictionary::finalize() } // if reversible and no specific uncraft recipe exists use this recipe - if( r.is_reversible() && !recipe_dict.uncraft.count( recipe_id( r.result() ) ) ) { - recipe_dict.uncraft[ recipe_id( r.result() ) ] = r; + if( r.is_reversible() && !recipe_dict.uncraft.count( recipe_id( r.result().str() ) ) ) { + recipe_dict.uncraft[ recipe_id( r.result().str() ) ] = r; } } // add pseudo uncrafting recipes for( const itype *e : item_controller->all() ) { const itype_id id = e->get_id(); - const recipe_id rid = recipe_id( id ); + const recipe_id rid = recipe_id( id.str() ); // books that don't already have an uncrafting recipe if( e->book && !recipe_dict.uncraft.count( rid ) && e->volume > 0_ml ) { diff --git a/src/recipe_dictionary.h b/src/recipe_dictionary.h index a9667404e0c61..26cd3392269ea 100644 --- a/src/recipe_dictionary.h +++ b/src/recipe_dictionary.h @@ -18,8 +18,6 @@ class JsonIn; class JsonOut; class JsonObject; -using itype_id = std::string; - class recipe_dictionary { friend class Item_factory; // allow removal of blacklisted recipes diff --git a/src/requirements.cpp b/src/requirements.cpp index 9de5599c6347c..6fa0b71a796a4 100644 --- a/src/requirements.cpp +++ b/src/requirements.cpp @@ -31,6 +31,18 @@ #include "translations.h" #include "visitable.h" +static const itype_id itype_char_forge( "char_forge" ); +static const itype_id itype_crucible( "crucible" ); +static const itype_id itype_fire( "fire" ); +static const itype_id itype_forge( "forge" ); +static const itype_id itype_mold_plastic( "mold_plastic" ); +static const itype_id itype_oxy_torch( "oxy_torch" ); +static const itype_id itype_press( "press" ); +static const itype_id itype_sewing_kit( "sewing_kit" ); +static const itype_id itype_UPS( "UPS" ); +static const itype_id itype_welder( "welder" ); +static const itype_id itype_welder_crude( "welder_crude" ); + static const trait_id trait_DEBUG_HS( "DEBUG_HS" ); static std::map requirements_all; @@ -188,11 +200,11 @@ void tool_comp::load( const JsonValue &value ) { if( value.test_string() ) { // constructions uses this format: [ "tool", ... ] - type = value.get_string(); + value.read( type, true ); count = -1; } else { JsonArray comp = value.get_array(); - type = comp.get_string( 0 ); + comp.read( 0, type, true ); count = comp.get_int( 1 ); requirement = comp.size() > 2 && comp.get_string( 2 ) == "LIST"; } @@ -216,7 +228,7 @@ void tool_comp::dump( JsonOut &jsout ) const void item_comp::load( const JsonValue &value ) { JsonArray comp = value.get_array(); - type = comp.get_string( 0 ); + comp.read( 0, type, true ); count = comp.get_int( 1 ); size_t handled = 2; while( comp.size() > handled ) { @@ -457,7 +469,7 @@ template void inline_requirements( std::vector< std::vector > &list, Getter getter ) { std::set already_nested; - for( auto &vec : list ) { + for( std::vector &vec : list ) { // We always need to restart from the beginning in case of vector relocation while( true ) { auto iter = std::find_if( vec.begin(), vec.end(), []( const T & req ) { @@ -467,7 +479,7 @@ void inline_requirements( std::vector< std::vector > &list, Getter getter ) break; } - const auto req_id = requirement_id( iter->type ); + const auto req_id = requirement_id( iter->type.str() ); if( !req_id.is_valid() ) { debugmsg( "Tried to inline unknown requirement %s", req_id.c_str() ); return; @@ -560,7 +572,7 @@ std::vector requirement_data::get_folded_list( int width, const std::string color_tag = get_tag_from_color( color ); int qty = 0; if( component.get_component_type() == component_type::ITEM ) { - const itype_id item_id = static_cast( component.type ); + const itype_id item_id = itype_id( component.type.str() ); if( item::count_by_charges( item_id ) ) { qty = crafting_inv.charges_of( item_id, INT_MAX, filter ); } else { @@ -675,7 +687,7 @@ bool requirement_data::has_comps( const inventory &crafting_inv, } if( total_UPS_charges_used > 0 && - total_UPS_charges_used > crafting_inv.charges_of( "UPS" ) ) { + total_UPS_charges_used > crafting_inv.charges_of( itype_UPS ) ) { return false; } return retval; @@ -838,7 +850,7 @@ bool requirement_data::check_enough_materials( const item_comp &comp, const inve } template -static bool apply_blacklist( std::vector> &vec, const std::string &id ) +static bool apply_blacklist( std::vector> &vec, const itype_id &id ) { // remove all instances of @id type from each of the options for( auto &opts : vec ) { @@ -860,15 +872,15 @@ static bool apply_blacklist( std::vector> &vec, const std::string return blacklisted; } -void requirement_data::blacklist_item( const std::string &id ) +void requirement_data::blacklist_item( const itype_id &id ) { blacklisted |= apply_blacklist( tools, id ); blacklisted |= apply_blacklist( components, id ); } template -static void apply_replacement( std::vector> &vec, const std::string &id, - const std::string &replacement ) +static void apply_replacement( std::vector> &vec, const itype_id &id, + const itype_id &replacement ) { // If the target and replacement are both present, remove the target. // If only the target is present, replace it. @@ -938,32 +950,32 @@ requirement_data requirement_data::disassembly_requirements() const const itype_id &type = tool.type; // If crafting required a welder or forge then disassembly requires metal sawing - if( type == "welder" || type == "welder_crude" || type == "oxy_torch" || - type == "forge" || type == "char_forge" ) { + if( type == itype_welder || type == itype_welder_crude || type == itype_oxy_torch || + type == itype_forge || type == itype_char_forge ) { new_qualities.emplace_back( quality_id( "SAW_M_FINE" ), 1, 1 ); replaced = true; break; } //This only catches instances where the two tools are explicitly stated, and not just the required sewing quality - if( type == "sewing_kit" || - type == "mold_plastic" ) { + if( type == itype_sewing_kit || + type == itype_mold_plastic ) { new_qualities.emplace_back( quality_id( "CUT" ), 1, 1 ); replaced = true; break; } - if( type == "crucible" ) { + if( type == itype_crucible ) { replaced = true; break; } //This ensures that you don't need a hand press to break down reloaded ammo. - if( type == "press" ) { + if( type == itype_press ) { replaced = true; remove_fire = true; new_qualities.emplace_back( quality_id( "PULL" ), 1, 1 ); break; } - if( type == "fire" && remove_fire ) { + if( type == itype_fire && remove_fire ) { replaced = true; break; } diff --git a/src/requirements.h b/src/requirements.h index 4b9dc34d57be8..5e9f7585971b6 100644 --- a/src/requirements.h +++ b/src/requirements.h @@ -25,9 +25,6 @@ class item; class nc_color; class player; -// Denotes the id of an item type -using itype_id = std::string; - enum class available_status : int { a_true = +1, // yes, it's available a_false = -1, // no, it's not available @@ -54,7 +51,7 @@ struct quality { }; struct component { - itype_id type = "null"; + itype_id type = itype_id::NULL_ID(); int count = 0; // -1 means the player doesn't have the item, 1 means they do, // 0 means they have item but not enough for both tool and component diff --git a/src/savegame_json.cpp b/src/savegame_json.cpp index 63d5baf90f162..a26ef7fe9b437 100644 --- a/src/savegame_json.cpp +++ b/src/savegame_json.cpp @@ -118,6 +118,12 @@ static const activity_id ACT_AIM( "ACT_AIM" ); static const efftype_id effect_riding( "riding" ); +static const itype_id itype_battery( "battery" ); +static const itype_id itype_rad_badge( "rad_badge" ); +static const itype_id itype_radio( "radio" ); +static const itype_id itype_radio_on( "radio_on" ); +static const itype_id itype_usb_drive( "usb_drive" ); + static const ter_str_id t_ash( "t_ash" ); static const ter_str_id t_rubble( "t_rubble" ); static const ter_str_id t_pwr_sb_support_l( "t_pwr_sb_support_l" ); @@ -1206,7 +1212,8 @@ void avatar::load( const JsonObject &data ) data.read( "show_map_memory", show_map_memory ); for( JsonArray pair : data.get_array( "assigned_invlet" ) ) { - inv.assigned_invlet[static_cast( pair.get_int( 0 ) )] = pair.get_string( 1 ); + inv.assigned_invlet[static_cast( pair.get_int( 0 ) )] = + itype_id( pair.get_string( 1 ) ); } if( data.has_member( "invcache" ) ) { @@ -1796,7 +1803,7 @@ void inventory::json_save_invcache( JsonOut &json ) const json.start_array(); for( const auto &elem : invlet_cache.get_invlets_by_id() ) { json.start_object(); - json.member( elem.first ); + json.member( elem.first.str() ); json.start_array(); for( const auto &_sym : elem.second ) { json.write( static_cast( _sym ) ); @@ -1820,7 +1827,7 @@ void inventory::json_load_invcache( JsonIn &jsin ) for( const int i : member.get_array() ) { invlets.push_back( i ); } - map[member.name()] = invlets; + map[itype_id( member.name() )] = invlets; } } invlet_cache = { map }; @@ -2006,7 +2013,7 @@ void monster::load( const JsonObject &data ) // legacy loading for milkable creatures, fix mismatch. if( has_flag( MF_MILKABLE ) && !type->starting_ammo.empty() && !ammo.empty() && type->starting_ammo.begin()->first != ammo.begin()->first ) { - const std::string old_type = ammo.begin()->first; + const itype_id old_type = ammo.begin()->first; const int old_value = ammo.begin()->second; ammo[type->starting_ammo.begin()->first] = old_value; ammo.erase( old_type ); @@ -2195,7 +2202,7 @@ static std::set charge_removal_blacklist; void load_charge_removal_blacklist( const JsonObject &jo, const std::string &src ); void load_charge_removal_blacklist( const JsonObject &jo, const std::string &/*src*/ ) { - charge_removal_blacklist = jo.get_tags( "list" ); + jo.read( "list", charge_removal_blacklist ); } template @@ -2203,16 +2210,16 @@ void item::io( Archive &archive ) { itype_id orig; // original ID as loaded from JSON - const auto load_type = [&]( const itype_id & id ) { - orig = id; - convert( item_controller->migrate_id( id ) ); + const auto load_type = [&]( const std::string & id ) { + orig = itype_id( id ); + convert( item_controller->migrate_id( orig ) ); }; const auto load_curammo = [this]( const std::string & id ) { - curammo = item::find_type( item_controller->migrate_id( id ) ); + curammo = item::find_type( item_controller->migrate_id( itype_id( id ) ) ); }; const auto load_corpse = [this]( const std::string & id ) { - if( id == "null" ) { + if( itype_id( id ).is_null() ) { // backwards compatibility, nullptr should not be stored at all corpse = nullptr; } else { @@ -2220,7 +2227,7 @@ void item::io( Archive &archive ) } }; archive.template io( "typeid", type, load_type, []( const itype & i ) { - return i.get_id(); + return i.get_id().str(); }, io::required_tag() ); // normalize legacy saves to always have charges >= 0 @@ -2262,7 +2269,7 @@ void item::io( Archive &archive ) archive.io( "recipe_charges", recipe_charges, 1 ); archive.template io( "curammo", curammo, load_curammo, []( const itype & i ) { - return i.get_id(); + return i.get_id().str(); } ); archive.template io( "corpse", corpse, load_corpse, []( const mtype & i ) { @@ -2299,10 +2306,10 @@ void item::io( Archive &archive ) if( poison != 0 && note == 0 && !type->snippet_category.empty() ) { std::swap( note, poison ); } - if( poison != 0 && frequency == 0 && ( typeId() == "radio_on" || typeId() == "radio" ) ) { + if( poison != 0 && frequency == 0 && ( typeId() == itype_radio_on || typeId() == itype_radio ) ) { std::swap( frequency, poison ); } - if( poison != 0 && irradiation == 0 && typeId() == "rad_badge" ) { + if( poison != 0 && irradiation == 0 && typeId() == itype_rad_badge ) { std::swap( irradiation, poison ); } @@ -2371,7 +2378,8 @@ void item::io( Archive &archive ) // Types that are known to have charges, but should not have them. // We fix it here, but it's expected from bugged saves and does not require a message. if( charge_removal_blacklist.count( type->get_id() ) == 0 ) { - debugmsg( "Item %s was loaded with charges, but can not have any!", type->get_id() ); + debugmsg( "Item %s was loaded with charges, but can not have any!", + type->get_id().str() ); } charges = 0; } @@ -2384,7 +2392,7 @@ void item::migrate_content_item( const item &contained ) } else if( !contained.made_of( LIQUID ) && ( contained.is_magazine() || contained.is_ammo() ) ) { put_in( contained, item_pocket::pocket_type::MAGAZINE ); - } else if( typeId() == "usb_drive" ) { + } else if( typeId() == itype_usb_drive ) { // as of this migration, only usb_drive has any software in it. put_in( contained, item_pocket::pocket_type::SOFTWARE ); } else if( is_corpse() ) { @@ -2451,7 +2459,7 @@ void vehicle_part::deserialize( JsonIn &jsin ) vpart_id pid; data.read( "id", pid ); - std::map> deprecated = { + std::map> deprecated = { { "laser_gun", { "laser_rifle", "none" } }, { "seat_nocargo", { "seat", "none" } }, { "engine_plasma", { "minireactor", "none" } }, @@ -2498,7 +2506,7 @@ void vehicle_part::deserialize( JsonIn &jsin ) auto dep = deprecated.find( pid.str() ); if( dep != deprecated.end() ) { pid = vpart_id( dep->second.first ); - legacy_fuel = dep->second.second; + legacy_fuel = itype_id( dep->second.second ); } // if we don't know what type of part it is, it'll cause problems later. @@ -2541,13 +2549,13 @@ void vehicle_part::deserialize( JsonIn &jsin ) data.read( "target_second_z", target.second.z ); data.read( "ammo_pref", ammo_pref ); - if( legacy_fuel.empty() ) { + if( legacy_fuel.is_empty() ) { legacy_fuel = id.obj().fuel_type; } // with VEHICLE tag migrate fuel tanks only if amount field exists if( base.has_flag( "VEHICLE" ) ) { - if( data.has_int( "amount" ) && ammo_capacity() > 0 && legacy_fuel != "battery" ) { + if( data.has_int( "amount" ) && ammo_capacity() > 0 && legacy_fuel != itype_battery ) { ammo_set( legacy_fuel, data.get_int( "amount" ) ); } @@ -2920,7 +2928,7 @@ void mission::deserialize( JsonIn &jsin ) follow_up = mission_type_id( jo.get_string( "follow_up" ) ); } - item_id = itype_id( jo.get_string( "item_id", item_id ) ); + jo.read( "item_id", item_id ); const std::string omid = jo.get_string( "target_id", "" ); if( !omid.empty() ) { @@ -3172,7 +3180,7 @@ void player_morale::morale_point::deserialize( JsonIn &jsin ) if( !jo.read( "type", type ) ) { type = morale_type_data::convert_legacy( jo.get_int( "type_enum" ) ); } - std::string tmpitype; + itype_id tmpitype; if( jo.read( "item_type", tmpitype ) && item::type_is_defined( tmpitype ) ) { item_type = item::find_type( tmpitype ); } diff --git a/src/sounds.cpp b/src/sounds.cpp index 22bb394f44809..39f5357ea44d3 100644 --- a/src/sounds.cpp +++ b/src/sounds.cpp @@ -81,10 +81,13 @@ static const efftype_id effect_slept_through_alarm( "slept_through_alarm" ); static const trait_id trait_HEAVYSLEEPER2( "HEAVYSLEEPER2" ); static const trait_id trait_HEAVYSLEEPER( "HEAVYSLEEPER" ); + static const itype_id fuel_type_muscle( "muscle" ); static const itype_id fuel_type_wind( "wind" ); static const itype_id fuel_type_battery( "battery" ); +static const itype_id itype_weapon_fire_suppressed( "weapon_fire_suppressed" ); + struct sound_event { int volume; sounds::sound_t category; @@ -984,7 +987,7 @@ void sfx::generate_gun_sound( const player &source_arg, const item &firing ) []( const item * e ) { return e->type->gunmod->loudness < 0; } ) ) { - weapon_id = "weapon_fire_suppressed"; + weapon_id = itype_weapon_fire_suppressed; } } else { @@ -997,7 +1000,7 @@ void sfx::generate_gun_sound( const player &source_arg, const item &firing ) } } - play_variant_sound( selected_sound, weapon_id, heard_volume, angle, 0.8, 1.2 ); + play_variant_sound( selected_sound, weapon_id.str(), heard_volume, angle, 0.8, 1.2 ); start_sfx_timestamp = std::chrono::high_resolution_clock::now(); } diff --git a/src/string_id_null_ids.cpp b/src/string_id_null_ids.cpp index d64b2a2ef422c..13e62db71bf8f 100644 --- a/src/string_id_null_ids.cpp +++ b/src/string_id_null_ids.cpp @@ -38,6 +38,7 @@ MAKE_NULL_ID( translation, "null" ) return id; \ } +MAKE_NULL_ID2( itype, "null" ) MAKE_NULL_ID2( mtype, "mon_null" ) MAKE_NULL_ID2( oter_t, "", 0 ) MAKE_NULL_ID2( oter_type_t, "", 0 ) diff --git a/src/suffer.cpp b/src/suffer.cpp index e4f4d821e03c9..6d6f0a3144350 100644 --- a/src/suffer.cpp +++ b/src/suffer.cpp @@ -103,6 +103,12 @@ static const efftype_id effect_valium( "valium" ); static const efftype_id effect_visuals( "visuals" ); static const efftype_id effect_winded( "winded" ); +static const itype_id itype_e_handcuffs( "e_handcuffs" ); +static const itype_id itype_inhaler( "inhaler" ); +static const itype_id itype_smoxygen_tank( "smoxygen_tank" ); +static const itype_id itype_oxygen_tank( "oxygen_tank" ); +static const itype_id itype_rad_badge( "rad_badge" ); + static const trait_id trait_ADDICTIVE( "ADDICTIVE" ); static const trait_id trait_ALBINO( "ALBINO" ); static const trait_id trait_ASTHMA( "ASTHMA" ); @@ -613,8 +619,8 @@ void Character::suffer_from_asthma( const int current_stim ) ( has_effect( effect_sleep ) ? 10 : 1 ) ) ) { return; } - bool auto_use = has_charges( "inhaler", 1 ) || has_charges( "oxygen_tank", 1 ) || - has_charges( "smoxygen_tank", 1 ); + bool auto_use = has_charges( itype_inhaler, 1 ) || has_charges( itype_oxygen_tank, 1 ) || + has_charges( itype_smoxygen_tank, 1 ); bool oxygenator = has_bionic( bio_gills ) && get_power_level() >= 3_kJ; if( underwater ) { oxygen = oxygen / 2; @@ -628,29 +634,29 @@ void Character::suffer_from_asthma( const int current_stim ) inventory map_inv; map_inv.form_from_map( g->u.pos(), 2, &g->u ); // check if an inhaler is somewhere near - bool nearby_use = auto_use || oxygenator || map_inv.has_charges( "inhaler", 1 ) || - map_inv.has_charges( "oxygen_tank", 1 ) || - map_inv.has_charges( "smoxygen_tank", 1 ); + bool nearby_use = auto_use || oxygenator || map_inv.has_charges( itype_inhaler, 1 ) || + map_inv.has_charges( itype_oxygen_tank, 1 ) || + map_inv.has_charges( itype_smoxygen_tank, 1 ); // check if character has an oxygenator first if( oxygenator ) { mod_power_level( -3_kJ ); add_msg_if_player( m_info, _( "You use your Oxygenator to clear it up, " "then go back to sleep." ) ); } else if( auto_use ) { - if( use_charges_if_avail( "inhaler", 1 ) ) { + if( use_charges_if_avail( itype_inhaler, 1 ) ) { add_msg_if_player( m_info, _( "You use your inhaler and go back to sleep." ) ); - } else if( use_charges_if_avail( "oxygen_tank", 1 ) || - use_charges_if_avail( "smoxygen_tank", 1 ) ) { + } else if( use_charges_if_avail( itype_oxygen_tank, 1 ) || + use_charges_if_avail( itype_smoxygen_tank, 1 ) ) { add_msg_if_player( m_info, _( "You take a deep breath from your oxygen tank " "and go back to sleep." ) ); } } else if( nearby_use ) { // create new variable to resolve a reference issue int amount = 1; - if( !g->m.use_charges( g->u.pos(), 2, "inhaler", amount ).empty() ) { + if( !g->m.use_charges( g->u.pos(), 2, itype_inhaler, amount ).empty() ) { add_msg_if_player( m_info, _( "You use your inhaler and go back to sleep." ) ); - } else if( !g->m.use_charges( g->u.pos(), 2, "oxygen_tank", amount ).empty() || - !g->m.use_charges( g->u.pos(), 2, "smoxygen_tank", amount ).empty() ) { + } else if( !g->m.use_charges( g->u.pos(), 2, itype_oxygen_tank, amount ).empty() || + !g->m.use_charges( g->u.pos(), 2, itype_smoxygen_tank, amount ).empty() ) { add_msg_if_player( m_info, _( "You take a deep breath from your oxygen tank " "and go back to sleep." ) ); } @@ -667,9 +673,9 @@ void Character::suffer_from_asthma( const int current_stim ) } } else if( auto_use ) { int charges = 0; - if( use_charges_if_avail( "inhaler", 1 ) ) { + if( use_charges_if_avail( itype_inhaler, 1 ) ) { moves -= 40; - charges = charges_of( "inhaler" ); + charges = charges_of( itype_inhaler ); if( charges == 0 ) { add_msg_if_player( m_bad, _( "You use your last inhaler charge." ) ); } else { @@ -679,10 +685,10 @@ void Character::suffer_from_asthma( const int current_stim ) "only %d charges left.", charges ), charges ); } - } else if( use_charges_if_avail( "oxygen_tank", 1 ) || - use_charges_if_avail( "smoxygen_tank", 1 ) ) { + } else if( use_charges_if_avail( itype_oxygen_tank, 1 ) || + use_charges_if_avail( itype_smoxygen_tank, 1 ) ) { moves -= 500; // synched with use action - charges = charges_of( "oxygen_tank" ) + charges_of( "smoxygen_tank" ); + charges = charges_of( itype_oxygen_tank ) + charges_of( itype_smoxygen_tank ); if( charges == 0 ) { add_msg_if_player( m_bad, _( "You breathe in last bit of oxygen " "from the tank." ) ); @@ -1165,7 +1171,7 @@ void Character::suffer_from_bad_bionics() moves -= 150; mod_power_level( -10_kJ ); - if( weapon.typeId() == "e_handcuffs" && weapon.charges > 0 ) { + if( weapon.typeId() == itype_e_handcuffs && weapon.charges > 0 ) { weapon.charges -= rng( 1, 3 ) * 50; if( weapon.charges < 1 ) { weapon.charges = 1; @@ -1512,7 +1518,7 @@ bool Character::irradiate( float rads, bool bypass ) // Apply rads to any radiation badges. for( item *const it : inv_dump() ) { - if( it->typeId() != "rad_badge" ) { + if( it->typeId() != itype_rad_badge ) { continue; } diff --git a/src/timed_event.cpp b/src/timed_event.cpp index ae43c35299d2e..150c26b49d51e 100644 --- a/src/timed_event.cpp +++ b/src/timed_event.cpp @@ -27,6 +27,8 @@ #include "translations.h" #include "type_id.h" +static const itype_id itype_petrified_eye( "petrified_eye" ); + static const mtype_id mon_amigara_horror( "mon_amigara_horror" ); static const mtype_id mon_copbot( "mon_copbot" ); static const mtype_id mon_dark_wyrm( "mon_dark_wyrm" ); @@ -79,7 +81,7 @@ void timed_event::actualize() } } // You could drop the flag, you know. - if( g->u.has_amount( "petrified_eye", 1 ) ) { + if( g->u.has_amount( itype_petrified_eye, 1 ) ) { sounds::sound( g->u.pos(), 60, sounds::sound_t::alert, _( "a tortured scream!" ), false, "shout", "scream_tortured" ); if( !g->u.is_deaf() ) { diff --git a/src/trap.cpp b/src/trap.cpp index 4c6cbfa5087c1..1876e035b224b 100644 --- a/src/trap.cpp +++ b/src/trap.cpp @@ -128,20 +128,20 @@ void trap::load( const JsonObject &jo, const std::string & ) optional( jo, was_loaded, "spell_data", spell_data ); assign( jo, "trigger_weight", trigger_weight ); for( const JsonValue entry : jo.get_array( "drops" ) ) { - std::string item_type; + itype_id item_type; int quantity = 0; int charges = 0; if( entry.test_object() ) { JsonObject jc = entry.get_object(); - item_type = jc.get_string( "item" ); + jc.read( "item", item_type, true ); quantity = jc.get_int( "quantity", 1 ); charges = jc.get_int( "charges", 1 ); } else { - item_type = entry.get_string(); + entry.read( item_type, true ); quantity = 1; charges = 1; } - if( !item_type.empty() && quantity > 0 && charges > 0 ) { + if( !item_type.is_empty() && quantity > 0 && charges > 0 ) { components.emplace_back( std::make_tuple( item_type, quantity, charges ) ); } } @@ -162,9 +162,10 @@ void trap::load( const JsonObject &jo, const std::string & ) for( const JsonValue entry : jv.get_array( "spawn_items" ) ) { if( entry.test_object() ) { JsonObject joitm = entry.get_object(); - vehicle_data.spawn_items.emplace_back( joitm.get_string( "id" ), joitm.get_float( "chance" ) ); + vehicle_data.spawn_items.emplace_back( + itype_id( joitm.get_string( "id" ) ), joitm.get_float( "chance" ) ); } else { - vehicle_data.spawn_items.emplace_back( entry.get_string(), 1.0 ); + vehicle_data.spawn_items.emplace_back( itype_id( entry.get_string() ), 1.0 ); } } } @@ -261,7 +262,7 @@ bool trap::is_funnel() const void trap::on_disarmed( map &m, const tripoint &p ) const { for( auto &i : components ) { - const std::string &item_type = std::get<0>( i ); + const itype_id &item_type = std::get<0>( i ); const int quantity = std::get<1>( i ); const int charges = std::get<2>( i ); m.spawn_item( p.xy(), item_type, quantity, charges ); @@ -321,9 +322,9 @@ void trap::check_consistency() { for( const auto &t : trap_factory.get_all() ) { for( auto &i : t.components ) { - const std::string &item_type = std::get<0>( i ); + const itype_id &item_type = std::get<0>( i ); if( !item::type_is_defined( item_type ) ) { - debugmsg( "trap %s has unknown item as component %s", t.id.c_str(), item_type.c_str() ); + debugmsg( "trap %s has unknown item as component %s", t.id.str(), item_type.str() ); } } } diff --git a/src/trap.h b/src/trap.h index 3d7691739f5f8..bbc8cafd08137 100644 --- a/src/trap.h +++ b/src/trap.h @@ -66,8 +66,6 @@ bool cast_spell( const tripoint &p, Creature *critter, item * ); } // namespace trapfunc struct vehicle_handle_trap_data { - using itype_id = std::string; - bool remove_trap = false; bool do_explosion = false; bool is_falling = false; @@ -86,7 +84,6 @@ struct vehicle_handle_trap_data { using trap_function = std::function; struct trap { - using itype_id = std::string; trap_str_id id; trap_id loadid; @@ -115,7 +112,7 @@ struct trap { units::mass trigger_weight = units::mass( -1, units::mass::unit_type{} ); int funnel_radius_mm = 0; // For disassembly? - std::vector> components; + std::vector> components; public: // data required for trapfunc::spell() fake_spell spell_data; diff --git a/src/trapfunc.cpp b/src/trapfunc.cpp index ffccd36df31c0..564e6448a4e6b 100644 --- a/src/trapfunc.cpp +++ b/src/trapfunc.cpp @@ -50,6 +50,10 @@ static const efftype_id effect_ridden( "ridden" ); static const efftype_id effect_slimed( "slimed" ); static const efftype_id effect_tetanus( "tetanus" ); +static const itype_id itype_bullwhip( "bullwhip" ); +static const itype_id itype_grapnel( "grapnel" ); +static const itype_id itype_rope_30( "rope_30" ); + static const trait_id trait_INFIMMUNE( "INFIMMUNE" ); static const trait_id trait_INFRESIST( "INFRESIST" ); static const trait_id trait_WINGS_BIRD( "WINGS_BIRD" ); @@ -1016,7 +1020,7 @@ bool trapfunc::portal( const tripoint &p, Creature *c, item *i ) } // Don't ask NPCs - they always want to do the first thing that comes to their minds -static bool query_for_item( const player *pl, const std::string &itemname, const char *que ) +static bool query_for_item( const player *pl, const itype_id &itemname, const char *que ) { return pl->has_amount( itemname, 1 ) && ( !pl->is_player() || query_yn( que ) ); } @@ -1028,7 +1032,7 @@ static tripoint random_neighbor( tripoint center ) return center; } -static bool sinkhole_safety_roll( player *p, const std::string &itemname, const int diff ) +static bool sinkhole_safety_roll( player *p, const itype_id &itemname, const int diff ) { ///\EFFECT_STR increases chance to attach grapnel, bullwhip, or rope when falling into a sinkhole @@ -1082,15 +1086,15 @@ bool trapfunc::sinkhole( const tripoint &p, Creature *c, item *i ) } } else if( pl != nullptr ) { bool success = false; - if( query_for_item( pl, "grapnel", + if( query_for_item( pl, itype_grapnel, _( "You step into a sinkhole! Throw your grappling hook out to try to catch something?" ) ) ) { - success = sinkhole_safety_roll( pl, "grapnel", 6 ); - } else if( query_for_item( pl, "bullwhip", + success = sinkhole_safety_roll( pl, itype_grapnel, 6 ); + } else if( query_for_item( pl, itype_bullwhip, _( "You step into a sinkhole! Throw your whip out to try and snag something?" ) ) ) { - success = sinkhole_safety_roll( pl, "bullwhip", 8 ); - } else if( query_for_item( pl, "rope_30", + success = sinkhole_safety_roll( pl, itype_bullwhip, 8 ); + } else if( query_for_item( pl, itype_rope_30, _( "You step into a sinkhole! Throw your rope out to try to catch something?" ) ) ) { - success = sinkhole_safety_roll( pl, "rope_30", 12 ); + success = sinkhole_safety_roll( pl, itype_rope_30, 12 ); } pl->add_msg_player_or_npc( m_warning, _( "The sinkhole collapses!" ), diff --git a/src/turret.cpp b/src/turret.cpp index 43cbb93eed626..d5b3a794ddfcc 100644 --- a/src/turret.cpp +++ b/src/turret.cpp @@ -116,7 +116,7 @@ const itype *turret_data::ammo_data() const return nullptr; } if( part->info().has_flag( "USE_TANKS" ) ) { - return ammo_current() != "null" ? item::find_type( ammo_current() ) : nullptr; + return !ammo_current().is_null() ? item::find_type( ammo_current() ) : nullptr; } return part->base.ammo_data(); } @@ -133,7 +133,7 @@ itype_id turret_data::ammo_current() const if( opts.count( part->base.ammo_default() ) ) { return part->base.ammo_default(); } - return opts.empty() ? "null" : *opts.begin(); + return opts.empty() ? itype_id::NULL_ID() : *opts.begin(); } std::set turret_data::ammo_options() const @@ -145,7 +145,7 @@ std::set turret_data::ammo_options() const } if( !part->info().has_flag( "USE_TANKS" ) ) { - if( part->base.ammo_current() != "null" ) { + if( !part->base.ammo_current().is_null() ) { opts.insert( part->base.ammo_current() ); } diff --git a/src/type_id.h b/src/type_id.h index 3e9b86584e029..b040b9248a676 100644 --- a/src/type_id.h +++ b/src/type_id.h @@ -66,6 +66,9 @@ using harvest_id = string_id; class item_category; using item_category_id = string_id; +struct itype; +using itype_id = string_id; + class ma_buff; using mabuff_id = string_id; diff --git a/src/uistate.h b/src/uistate.h index e673a92996bee..770e1d67f25a0 100644 --- a/src/uistate.h +++ b/src/uistate.h @@ -89,8 +89,6 @@ class uistatedata { /**** this will set a default value on startup, however to save, see below ****/ private: - // not needed for compilation, but keeps syntax plugins happy - using itype_id = std::string; enum side { left = 0, right = 1, NUM_PANES = 2 }; public: int ags_pay_gas_selected_pump = 0; @@ -102,8 +100,8 @@ class uistatedata int adv_inv_container_location = -1; int adv_inv_container_index = 0; - itype_id adv_inv_container_type = "null"; - itype_id adv_inv_container_content_type = "null"; + itype_id adv_inv_container_type = itype_id::NULL_ID(); + itype_id adv_inv_container_content_type = itype_id::NULL_ID(); bool adv_inv_container_in_vehicle = false; advanced_inv_save_state transfer_save; diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index 08061d2509933..9d36bf9868632 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -66,6 +66,10 @@ static const itype_id fuel_type_battery( "battery" ); +static const itype_id itype_battery( "battery" ); +static const itype_id itype_hose( "hose" ); +static const itype_id itype_plut_cell( "plut_cell" ); + static const skill_id skill_mechanics( "mechanics" ); static const quality_id qual_JACK( "JACK" ); @@ -199,7 +203,7 @@ veh_interact::veh_interact( vehicle &veh, const point &p ) // Only build the shapes map and the wheel list once for( const auto &e : vpart_info::all() ) { const vpart_info &vp = e.second; - vpart_shapes[ vp.name() + vp.item ].push_back( &vp ); + vpart_shapes[ vp.name() + vp.item.str() ].push_back( &vp ); if( vp.has_flag( "WHEEL" ) ) { wheel_types.push_back( &vp ); } @@ -576,7 +580,7 @@ task_reason veh_interact::cant_do( char mode ) break; } } - has_tools = crafting_inv.has_tools( "hose", 1 ); + has_tools = crafting_inv.has_tools( itype_hose, 1 ); break; case 'd': @@ -1061,7 +1065,8 @@ bool veh_interact::do_install( std::string &msg ) !query_yn( _( "Installing this part will make the vehicle unfoldable. Continue?" ) ) ) { return true; } - const auto &shapes = vpart_shapes[ sel_vpart_info->name() + sel_vpart_info->item ]; + const auto &shapes = + vpart_shapes[ sel_vpart_info->name() + sel_vpart_info->item.str() ]; int selected_shape = -1; if( shapes.size() > 1 ) { // more than one shape available, display selection std::vector shape_ui_entries; @@ -1453,11 +1458,13 @@ bool veh_interact::overview( std::function enabl if( pt.is_engine() && pt.is_available() ) { // if tank contains something then display the contents in milliliters auto details = []( const vehicle_part & pt, const catacurses::window & w, int y ) { - right_print( w, y, 1, item::find_type( pt.ammo_current() )->color, - string_format( "%s %s", - pt.fuel_current() != "null" ? item::nname( pt.fuel_current() ) : "", - //~ translation should not exceed 3 console cells - right_justify( pt.enabled ? _( "Yes" ) : _( "No" ), 3 ) ) ); + right_print( + w, y, 1, item::find_type( pt.ammo_current() )->color, + string_format( + "%s %s", + !pt.fuel_current().is_null() ? item::nname( pt.fuel_current() ) : "", + //~ translation should not exceed 3 console cells + right_justify( pt.enabled ? _( "Yes" ) : _( "No" ), 3 ) ) ); }; // display engine faults (if any) @@ -1481,7 +1488,7 @@ bool veh_interact::overview( std::function enabl for( vehicle_part &pt : veh->parts ) { if( pt.is_tank() && pt.is_available() ) { auto details = []( const vehicle_part & pt, const catacurses::window & w, int y ) { - if( pt.ammo_current() != "null" ) { + if( !pt.ammo_current().is_null() ) { std::string specials; // vehicle parts can only have one pocket, and we are showing a liquid, which can only be one. const item &it = pt.base.contents.legacy_front(); @@ -1516,7 +1523,7 @@ bool veh_interact::overview( std::function enabl enable( pt ) ? next_hotkey( hotkey ) : '\0', details ); } else if( pt.is_fuel_store() && !( pt.is_battery() || pt.is_reactor() ) && !pt.is_broken() ) { auto details = []( const vehicle_part & pt, const catacurses::window & w, int y ) { - if( pt.ammo_current() != "null" ) { + if( !pt.ammo_current().is_null() ) { const itype *pt_ammo_cur = item::find_type( pt.ammo_current() ); auto stack = units::legacy_volume_factor / pt_ammo_cur->stack_size; int offset = 1; @@ -2128,7 +2135,7 @@ void veh_interact::move_cursor( const point &d, int dstart_at ) continue; } if( veh->can_mount( vd, vp.get_id() ) ) { - if( vp.get_id() != vpart_shapes[ vp.name() + vp.item ][ 0 ]->get_id() ) { + if( vp.get_id() != vpart_shapes[ vp.name() + vp.item.str() ][ 0 ]->get_id() ) { // only add first shape to install list continue; } @@ -2761,7 +2768,7 @@ void veh_interact::display_details( const vpart_info *part ) // line 4 [horizontal]: fuel_type (if applicable) // line 4 [vertical/hybrid]: (column 1) fuel_type (if applicable) (column 2) power (if applicable) // line 5 [horizontal]: power (if applicable) - if( part->fuel_type != "null" ) { + if( !part->fuel_type.is_null() ) { fold_and_print( w_details, point( col_1, line + 4 ), column_width, c_white, _( "Charge: %s" ), item::nname( part->fuel_type ) ); @@ -2784,7 +2791,7 @@ void veh_interact::display_details( const vpart_info *part ) // 6 [horizontal]: (column 1) flags (column 2) battery capacity (if applicable) fold_and_print( w_details, point( col_1, line + 5 ), details_w, c_yellow, label ); - if( part->fuel_type == "battery" && !part->has_flag( VPFLAG_ENGINE ) && + if( part->fuel_type == itype_battery && !part->has_flag( VPFLAG_ENGINE ) && !part->has_flag( VPFLAG_ALTERNATOR ) ) { const cata::value_ptr &battery = item::find_type( part->item )->magazine; fold_and_print( w_details, point( col_2, line + 5 ), column_width, c_white, @@ -2894,7 +2901,7 @@ void act_vehicle_unload_fuel( vehicle *veh ) uilist smenu; smenu.text = _( "Remove what?" ); for( auto &fuel : fuels ) { - if( fuel == "plut_cell" && veh->fuel_left( fuel ) < PLUTONIUM_CHARGES ) { + if( fuel == itype_plut_cell && veh->fuel_left( fuel ) < PLUTONIUM_CHARGES ) { continue; } smenu.addentry( item::nname( fuel ) ); @@ -2910,7 +2917,7 @@ void act_vehicle_unload_fuel( vehicle *veh ) } int qty = veh->fuel_left( fuel ); - if( fuel == "plut_cell" ) { + if( fuel == itype_plut_cell ) { if( qty / PLUTONIUM_CHARGES == 0 ) { add_msg( m_info, _( "The vehicle has no charged plutonium cells." ) ); return; diff --git a/src/veh_type.cpp b/src/veh_type.cpp index 593e04234c0fa..433e57782b73c 100644 --- a/src/veh_type.cpp +++ b/src/veh_type.cpp @@ -614,14 +614,14 @@ void vpart_info::check() // Fuel type errors are serious and need fixing now if( !item::type_is_defined( part.fuel_type ) ) { debugmsg( "vehicle part %s uses undefined fuel %s", part.id.c_str(), part.item.c_str() ); - part.fuel_type = "null"; - } else if( part.fuel_type != "null" && !item::find_type( part.fuel_type )->fuel && + part.fuel_type = itype_id::NULL_ID(); + } else if( !part.fuel_type.is_null() && !item::find_type( part.fuel_type )->fuel && !type_can_contain( base_item_type, part.fuel_type ) ) { // HACK: Tanks are allowed to specify non-fuel "fuel", // because currently legacy blazemod uses it as a hack to restrict content types debugmsg( "non-tank vehicle part %s uses non-fuel item %s as fuel, setting to null", part.id.c_str(), part.fuel_type.c_str() ); - part.fuel_type = "null"; + part.fuel_type = itype_id::NULL_ID(); } if( part.has_flag( "TURRET" ) && !base_item_type.gun ) { debugmsg( "vehicle part %s has the TURRET flag, but is not made from a gun item", part.id.c_str() ); @@ -652,8 +652,8 @@ void vpart_info::check() } } if( part.has_flag( "WHEEL" ) && !base_item_type.wheel ) { - debugmsg( "vehicle part %s has the WHEEL flag, but base item %s is not a wheel. THIS WILL CRASH!", - part.id.c_str(), part.item ); + debugmsg( "vehicle part %s has the WHEEL flag, but base item %s is not a wheel. " + "THIS WILL CRASH!", part.id.str(), part.item.str() ); } for( auto &q : part.qualities ) { if( !q.first.is_valid() ) { @@ -1033,12 +1033,10 @@ void vehicle_prototype::load( const JsonObject &jo ) if( spawn_info.has_array( "items" ) ) { //Array of items that all spawn together (i.e. jack+tire) - for( const std::string line : spawn_info.get_array( "items" ) ) { - next_spawn.item_ids.push_back( line ); - } + spawn_info.read( "items", next_spawn.item_ids, true ); } else if( spawn_info.has_string( "items" ) ) { //Treat single item as array - next_spawn.item_ids.push_back( spawn_info.get_string( "items" ) ); + next_spawn.item_ids.push_back( itype_id( spawn_info.get_string( "items" ) ) ); } if( spawn_info.has_array( "item_groups" ) ) { //Pick from a group of items, just like map::place_items @@ -1121,7 +1119,7 @@ void vehicle_prototype::finalize() debugmsg( "init_vehicles: tank %s specified invalid fuel in %s", pt.part.c_str(), id.c_str() ); } } else { - if( pt.fuel != "null" ) { + if( !pt.fuel.is_null() ) { debugmsg( "init_vehicles: non-fuel store part %s with fuel in %s", pt.part.c_str(), id.c_str() ); } } diff --git a/src/veh_type.h b/src/veh_type.h index 936077456025c..36727e6fac291 100644 --- a/src/veh_type.h +++ b/src/veh_type.h @@ -22,9 +22,6 @@ #include "units.h" class player; - -using itype_id = std::string; - class JsonObject; class vehicle; @@ -210,10 +207,10 @@ class vpart_info std::set emissions; /** Fuel type of engine or tank */ - itype_id fuel_type = "null"; + itype_id fuel_type = itype_id::NULL_ID(); /** Default ammo (for turrets) */ - itype_id default_ammo = "null"; + itype_id default_ammo = itype_id::NULL_ID(); /** Volume of a foldable part when folded */ units::volume folded_volume = 0_ml; @@ -394,7 +391,7 @@ struct vehicle_prototype { int with_ammo = 0; std::set ammo_types; std::pair ammo_qty = { -1, -1 }; - itype_id fuel = "null"; + itype_id fuel = itype_id::NULL_ID(); }; vehicle_prototype(); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index a1166474d86fe..60971dc3c7d53 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -90,6 +90,12 @@ static const bionic_id bio_jointservo( "bio_jointservo" ); static const efftype_id effect_harnessed( "harnessed" ); static const efftype_id effect_winded( "winded" ); +static const itype_id itype_battery( "battery" ); +static const itype_id itype_plut_cell( "plut_cell" ); +static const itype_id itype_water( "water" ); +static const itype_id itype_water_clean( "water_clean" ); +static const itype_id itype_water_purifier( "water_purifier" ); + static const std::string flag_PERPETUAL( "PERPETUAL" ); static bool is_sm_tile_outside( const tripoint &real_global_pos ); @@ -501,34 +507,34 @@ void vehicle::init_state( int init_veh_fuel, int init_veh_status ) if( pt.is_reactor() ) { if( veh_fuel_mult == 100 ) { // Mint condition vehicle - pt.ammo_set( "plut_cell", pt.ammo_capacity() ); + pt.ammo_set( itype_plut_cell, pt.ammo_capacity() ); } else if( one_in( 2 ) && veh_fuel_mult > 0 ) { // Randomize charge a bit - pt.ammo_set( "plut_cell", pt.ammo_capacity() * ( veh_fuel_mult + rng( 0, 10 ) ) / 100 ); + pt.ammo_set( itype_plut_cell, pt.ammo_capacity() * ( veh_fuel_mult + rng( 0, 10 ) ) / 100 ); } else if( one_in( 2 ) && veh_fuel_mult > 0 ) { - pt.ammo_set( "plut_cell", pt.ammo_capacity() * ( veh_fuel_mult - rng( 0, 10 ) ) / 100 ); + pt.ammo_set( itype_plut_cell, pt.ammo_capacity() * ( veh_fuel_mult - rng( 0, 10 ) ) / 100 ); } else { - pt.ammo_set( "plut_cell", pt.ammo_capacity() * veh_fuel_mult / 100 ); + pt.ammo_set( itype_plut_cell, pt.ammo_capacity() * veh_fuel_mult / 100 ); } } if( pt.is_battery() ) { if( veh_fuel_mult == 100 ) { // Mint condition vehicle - pt.ammo_set( "battery", pt.ammo_capacity() ); + pt.ammo_set( itype_battery, pt.ammo_capacity() ); } else if( one_in( 2 ) && veh_fuel_mult > 0 ) { // Randomize battery ammo a bit - pt.ammo_set( "battery", pt.ammo_capacity() * ( veh_fuel_mult + rng( 0, 10 ) ) / 100 ); + pt.ammo_set( itype_battery, pt.ammo_capacity() * ( veh_fuel_mult + rng( 0, 10 ) ) / 100 ); } else if( one_in( 2 ) && veh_fuel_mult > 0 ) { - pt.ammo_set( "battery", pt.ammo_capacity() * ( veh_fuel_mult - rng( 0, 10 ) ) / 100 ); + pt.ammo_set( itype_battery, pt.ammo_capacity() * ( veh_fuel_mult - rng( 0, 10 ) ) / 100 ); } else { - pt.ammo_set( "battery", pt.ammo_capacity() * veh_fuel_mult / 100 ); + pt.ammo_set( itype_battery, pt.ammo_capacity() * veh_fuel_mult / 100 ); } } - if( pt.is_tank() && type->parts[p].fuel != "null" ) { + if( pt.is_tank() && !type->parts[p].fuel.is_null() ) { int qty = pt.ammo_capacity() * veh_fuel_mult / 100; qty *= std::max( item::find_type( type->parts[p].fuel )->stack_size, 1 ); qty /= to_milliliter( units::legacy_volume_factor ); pt.ammo_set( type->parts[ p ].fuel, qty ); - } else if( pt.is_fuel_store() && type->parts[p].fuel != "null" ) { + } else if( pt.is_fuel_store() && !type->parts[p].fuel.is_null() ) { int qty = pt.ammo_capacity() * veh_fuel_mult / 100; pt.ammo_set( type->parts[ p ].fuel, qty ); } @@ -1125,7 +1131,7 @@ bool vehicle::has_engine_conflict( const vpart_info *possible_conflict, bool vehicle::is_engine_type( const int e, const itype_id &ft ) const { - return parts[engines[e]].ammo_current() == "null" ? parts[engines[e]].fuel_current() == ft : + return parts[engines[e]].ammo_current().is_null() ? parts[engines[e]].fuel_current() == ft : parts[engines[e]].ammo_current() == ft; } @@ -6472,7 +6478,7 @@ std::map vehicle::fuels_left() const { std::map result; for( const auto &p : parts ) { - if( p.is_fuel_store() && p.ammo_current() != "null" ) { + if( p.is_fuel_store() && !p.ammo_current().is_null() ) { result[ p.ammo_current() ] += p.ammo_remaining(); } } @@ -6676,15 +6682,15 @@ void vehicle::update_time( const time_point &update_to ) double area = std::pow( pt.info().size / units::legacy_volume_factor, 2 ) * M_PI; int qty = roll_remainder( funnel_charges_per_turn( area, accum_weather.rain_amount ) ); int c_qty = qty + ( tank->can_reload( water_clean ) ? tank->ammo_remaining() : 0 ); - int cost_to_purify = c_qty * item::find_type( "water_purifier" )->charges_to_use(); + int cost_to_purify = c_qty * item::find_type( itype_water_purifier )->charges_to_use(); if( qty > 0 ) { if( has_part( global_part_pos3( pt ), "WATER_PURIFIER", true ) && - ( fuel_left( "battery", true ) > cost_to_purify ) ) { - tank->ammo_set( "water_clean", c_qty ); + ( fuel_left( itype_battery, true ) > cost_to_purify ) ) { + tank->ammo_set( itype_water_clean, c_qty ); discharge_battery( cost_to_purify ); } else { - tank->ammo_set( "water", tank->ammo_remaining() + qty ); + tank->ammo_set( itype_water, tank->ammo_remaining() + qty ); } invalidate_mass(); } diff --git a/src/vehicle.h b/src/vehicle.h index c8829d09bc63c..419e94a4b9b5b 100644 --- a/src/vehicle.h +++ b/src/vehicle.h @@ -434,7 +434,7 @@ struct vehicle_part { cata::colony items; // inventory /** Preferred ammo type when multiple are available */ - itype_id ammo_pref = "null"; + itype_id ammo_pref = itype_id::NULL_ID(); /** * What NPC (if any) is assigned to this part (seat, turret etc)? diff --git a/src/vehicle_display.cpp b/src/vehicle_display.cpp index 74b524c6c293c..c07b3bca5d003 100644 --- a/src/vehicle_display.cpp +++ b/src/vehicle_display.cpp @@ -22,6 +22,7 @@ #include "optional.h" static const std::string part_location_structure( "structure" ); +static const itype_id itype_battery( "battery" ); static const itype_id fuel_type_muscle( "muscle" ); std::string vehicle::disp_name() const @@ -155,9 +156,9 @@ int vehicle::print_part_list( const catacurses::window &win, int y1, const int m std::string partname = vp.name(); - if( vp.is_fuel_store() && vp.ammo_current() != "null" ) { + if( vp.is_fuel_store() && !vp.ammo_current().is_null() ) { if( detail ) { - if( vp.ammo_current() == "battery" ) { + if( vp.ammo_current() == itype_battery ) { partname += string_format( _( " (%s/%s charge)" ), vp.ammo_remaining(), vp.ammo_capacity() ); } else { const itype *pt_ammo_cur = item::find_type( vp.ammo_current() ); @@ -305,7 +306,7 @@ std::vector vehicle::get_printable_fuel_types() const { std::set opts; for( const auto &pt : parts ) { - if( pt.is_fuel_store() && pt.ammo_current() != "null" ) { + if( pt.is_fuel_store() && !pt.ammo_current().is_null() ) { opts.emplace( pt.ammo_current() ); } } diff --git a/src/vehicle_part.cpp b/src/vehicle_part.cpp index 9b4deab67d426..4a8a15454d2f1 100644 --- a/src/vehicle_part.cpp +++ b/src/vehicle_part.cpp @@ -28,6 +28,9 @@ static const itype_id fuel_type_battery( "battery" ); static const itype_id fuel_type_none( "null" ); +static const itype_id itype_battery( "battery" ); +static const itype_id itype_muscle( "muscle" ); + /*----------------------------------------------------------------------------- * VEHICLE_PART *-----------------------------------------------------------------------------*/ @@ -171,14 +174,14 @@ bool vehicle_part::is_available( const bool carried ) const itype_id vehicle_part::fuel_current() const { if( is_engine() ) { - if( ammo_pref == "null" ) { - return info().fuel_type != "muscle" ? info().fuel_type : "null"; + if( ammo_pref.is_null() ) { + return info().fuel_type != itype_muscle ? info().fuel_type : itype_id::NULL_ID(); } else { return ammo_pref; } } - return "null"; + return itype_id::NULL_ID(); } bool vehicle_part::fuel_set( const itype_id &fuel ) @@ -197,7 +200,7 @@ bool vehicle_part::fuel_set( const itype_id &fuel ) itype_id vehicle_part::ammo_current() const { if( is_battery() ) { - return "battery"; + return itype_battery; } if( is_tank() && !base.contents.empty() ) { @@ -208,7 +211,7 @@ itype_id vehicle_part::ammo_current() const return base.ammo_current(); } - return "null"; + return itype_id::NULL_ID(); } int vehicle_part::ammo_capacity() const @@ -338,7 +341,7 @@ bool vehicle_part::can_reload( const item &obj ) const return false; } // prevent mixing of different ammo - if( ammo_current() != "null" && ammo_current() != obj_type ) { + if( !ammo_current().is_null() && ammo_current() != obj_type ) { return false; } // For storage with set type, prevent filling with different types diff --git a/src/vehicle_use.cpp b/src/vehicle_use.cpp index de26d8d636a27..dbab36c4b7c9e 100644 --- a/src/vehicle_use.cpp +++ b/src/vehicle_use.cpp @@ -62,6 +62,16 @@ static const itype_id fuel_type_muscle( "muscle" ); static const itype_id fuel_type_none( "null" ); static const itype_id fuel_type_wind( "wind" ); +static const itype_id itype_battery( "battery" ); +static const itype_id itype_detergent( "detergent" ); +static const itype_id itype_fungal_seeds( "fungal_seeds" ); +static const itype_id itype_hotplate( "hotplate" ); +static const itype_id itype_marloss_seed( "marloss_seed" ); +static const itype_id itype_water( "water" ); +static const itype_id itype_water_clean( "water_clean" ); +static const itype_id itype_water_purifier( "water_purifier" ); +static const itype_id itype_welder( "welder" ); + static const efftype_id effect_harnessed( "harnessed" ); static const efftype_id effect_tied( "tied" ); @@ -1284,8 +1294,8 @@ void vehicle::operate_reaper() map_stack::iterator seed = std::find_if( items.begin(), items.end(), []( const item & it ) { return it.is_seed(); } ); - if( seed == items.end() || seed->typeId() == "fungal_seeds" || - seed->typeId() == "marloss_seed" ) { + if( seed == items.end() || seed->typeId() == itype_fungal_seeds || + seed->typeId() == itype_marloss_seed ) { // Otherworldly plants, the earth-made reaper can not handle those. continue; } @@ -1524,7 +1534,7 @@ void vehicle::use_autoclave( int p ) _( "You turn the autoclave off before it's finished the program, and open its door." ) ); } else if( items.empty() ) { add_msg( m_bad, _( "The autoclave is empty, there's no point in starting it." ) ); - } else if( fuel_left( "water" ) < 8 && fuel_left( "water_clean" ) < 8 ) { + } else if( fuel_left( itype_water ) < 8 && fuel_left( itype_water_clean ) < 8 ) { add_msg( m_bad, _( "You need 8 charges of water in tanks of the %s for the autoclave to run." ), name ); } else if( filthy_items ) { @@ -1540,10 +1550,10 @@ void vehicle::use_autoclave( int p ) n.set_age( 0_turns ); } - if( fuel_left( "water" ) >= 8 ) { - drain( "water", 8 ); + if( fuel_left( itype_water ) >= 8 ) { + drain( itype_water, 8 ); } else { - drain( "water_clean", 8 ); + drain( itype_water_clean, 8 ); } add_msg( m_good, @@ -1576,7 +1586,7 @@ void vehicle::use_washing_machine( int p ) } else if( items.empty() ) { add_msg( m_bad, _( "The washing machine is empty, there's no point in starting it." ) ); - } else if( fuel_left( "water" ) < 24 && fuel_left( "water_clean" ) < 24 ) { + } else if( fuel_left( itype_water ) < 24 && fuel_left( itype_water_clean ) < 24 ) { add_msg( m_bad, _( "You need 24 charges of water in tanks of the %s to fill the washing machine." ), name ); } else if( detergents.empty() ) { @@ -1621,10 +1631,10 @@ void vehicle::use_washing_machine( int p ) n.set_age( 0_turns ); } - if( fuel_left( "water" ) >= 24 ) { - drain( "water", 24 ); + if( fuel_left( itype_water ) >= 24 ) { + drain( itype_water, 24 ); } else { - drain( "water_clean", 24 ); + drain( itype_water_clean, 24 ); } std::vector detergent; @@ -1638,7 +1648,7 @@ void vehicle::use_washing_machine( int p ) void vehicle::use_dishwasher( int p ) { - bool detergent_is_enough = g->u.crafting_inventory().has_charges( "detergent", 5 ); + bool detergent_is_enough = g->u.crafting_inventory().has_charges( itype_detergent, 5 ); auto items = get_items( p ); static const std::string filthy( "FILTHY" ); bool filthy_items = std::all_of( items.begin(), items.end(), []( const item & i ) { @@ -1662,7 +1672,7 @@ void vehicle::use_dishwasher( int p ) } else if( items.empty() ) { add_msg( m_bad, _( "The dishwasher is empty, there's no point in starting it." ) ); - } else if( fuel_left( "water" ) < 24 && fuel_left( "water_clean" ) < 24 ) { + } else if( fuel_left( itype_water ) < 24 && fuel_left( itype_water_clean ) < 24 ) { add_msg( m_bad, _( "You need 24 charges of water in tanks of the %s to fill the dishwasher." ), name ); } else if( !detergent_is_enough ) { @@ -1678,14 +1688,14 @@ void vehicle::use_dishwasher( int p ) n.set_age( 0_turns ); } - if( fuel_left( "water" ) >= 24 ) { - drain( "water", 24 ); + if( fuel_left( itype_water ) >= 24 ) { + drain( itype_water, 24 ); } else { - drain( "water_clean", 24 ); + drain( itype_water_clean, 24 ); } std::vector detergent; - detergent.push_back( item_comp( "detergent", 5 ) ); + detergent.push_back( item_comp( itype_detergent, 5 ) ); g->u.consume_items( detergent, 1, is_crafting_component ); add_msg( m_good, @@ -1963,25 +1973,25 @@ void vehicle::interact_with( const tripoint &pos, int interact_part ) if( curtain_part >= 0 && curtain_closed ) { selectmenu.addentry( PEEK_CURTAIN, true, 'p', _( "Peek through the closed curtains" ) ); } - if( ( has_kitchen || has_chemlab ) && fuel_left( "battery", true ) > 0 ) { + if( ( has_kitchen || has_chemlab ) && fuel_left( itype_battery, true ) > 0 ) { selectmenu.addentry( USE_HOTPLATE, true, 'h', _( "Use the hotplate" ) ); } - if( has_faucet && fuel_left( "water_clean" ) > 0 ) { + if( has_faucet && fuel_left( itype_water_clean ) > 0 ) { selectmenu.addentry( FILL_CONTAINER, true, 'c', _( "Fill a container with water" ) ); selectmenu.addentry( DRINK, true, 'd', _( "Have a drink" ) ); } if( has_towel ) { selectmenu.addentry( USE_TOWEL, true, 't', _( "Use a towel" ) ); } - if( has_weldrig && fuel_left( "battery", true ) > 0 ) { + if( has_weldrig && fuel_left( itype_battery, true ) > 0 ) { selectmenu.addentry( USE_WELDER, true, 'w', _( "Use the welding rig" ) ); } if( has_purify ) { - bool can_purify = fuel_left( "battery", true ) >= - item::find_type( "water_purifier" )->charges_to_use(); + bool can_purify = fuel_left( itype_battery, true ) >= + item::find_type( itype_water_purifier )->charges_to_use(); selectmenu.addentry( USE_PURIFIER, can_purify, 'p', _( "Purify water in carried container" ) ); - selectmenu.addentry( PURIFY_TANK, can_purify && fuel_left( "water" ), + selectmenu.addentry( PURIFY_TANK, can_purify && fuel_left( itype_water ), 'P', _( "Purify water in vehicle tank" ) ); } if( has_monster_capture ) { @@ -2016,12 +2026,12 @@ void vehicle::interact_with( const tripoint &pos, int interact_part ) } auto veh_tool = [&]( const itype_id & obj ) { item pseudo( obj ); - if( fuel_left( "battery", true ) < pseudo.ammo_required() ) { + if( fuel_left( itype_battery, true ) < pseudo.ammo_required() ) { return false; } auto capacity = pseudo.ammo_capacity( true ); auto qty = capacity - discharge_battery( capacity ); - pseudo.ammo_set( "battery", qty ); + pseudo.ammo_set( itype_battery, qty ); g->u.invoke_item( &pseudo ); charge_battery( pseudo.ammo_remaining() ); return true; @@ -2046,7 +2056,7 @@ void vehicle::interact_with( const tripoint &pos, int interact_part ) return; } case USE_HOTPLATE: { - veh_tool( "hotplate" ); + veh_tool( itype_hotplate ); return; } case USE_TOWEL: { @@ -2066,19 +2076,19 @@ void vehicle::interact_with( const tripoint &pos, int interact_part ) return; } case FILL_CONTAINER: { - g->u.siphon( *this, "water_clean" ); + g->u.siphon( *this, itype_water_clean ); return; } case DRINK: { item water( "water_clean", 0 ); if( g->u.can_consume( water ) ) { g->u.assign_activity( player_activity( consume_activity_actor( water, false ) ) ); - drain( "water_clean", 1 ); + drain( itype_water_clean, 1 ); } return; } case USE_WELDER: { - if( veh_tool( "welder" ) ) { + if( veh_tool( itype_welder ) ) { // HACK: Evil hack incoming auto &act = g->u.activity; if( act.id() == ACT_REPAIR_ITEM ) { @@ -2094,19 +2104,20 @@ void vehicle::interact_with( const tripoint &pos, int interact_part ) return; } case USE_PURIFIER: { - veh_tool( "water_purifier" ); + veh_tool( itype_water_purifier ); return; } case PURIFY_TANK: { auto sel = []( const vehicle_part & pt ) { - return pt.is_tank() && pt.ammo_current() == "water"; + return pt.is_tank() && pt.ammo_current() == itype_water; }; - auto title = string_format( _( "Purify water in tank" ), - get_all_colors().get_name( item::find_type( "water" )->color ) ); + auto title = string_format( + _( "Purify water in tank" ), + get_all_colors().get_name( item::find_type( itype_water )->color ) ); auto &tank = veh_interact::select_part( *this, sel, title ); if( tank ) { - double cost = item::find_type( "water_purifier" )->charges_to_use(); - if( fuel_left( "battery", true ) < tank.ammo_remaining() * cost ) { + double cost = item::find_type( itype_water_purifier )->charges_to_use(); + if( fuel_left( itype_battery, true ) < tank.ammo_remaining() * cost ) { //~ $1 - vehicle name, $2 - part name add_msg( m_bad, _( "Insufficient power to purify the contents of the %1$s's %2$s" ), name, tank.name() ); @@ -2114,7 +2125,7 @@ void vehicle::interact_with( const tripoint &pos, int interact_part ) //~ $1 - vehicle name, $2 - part name add_msg( m_good, _( "You purify the contents of the %1$s's %2$s" ), name, tank.name() ); discharge_battery( tank.ammo_remaining() * cost ); - tank.ammo_set( "water_clean", tank.ammo_remaining() ); + tank.ammo_set( itype_water_clean, tank.ammo_remaining() ); } } return; diff --git a/src/visitable.cpp b/src/visitable.cpp index 4d3984d673d26..3f7ab52a0f796 100644 --- a/src/visitable.cpp +++ b/src/visitable.cpp @@ -33,6 +33,12 @@ #include "vehicle.h" #include "vehicle_selector.h" +static const itype_id itype_apparatus( "apparatus" ); +static const itype_id itype_adv_UPS_off( "adv_UPS_off" ); +static const itype_id itype_toolset( "toolset" ); +static const itype_id itype_UPS( "UPS" ); +static const itype_id itype_UPS_off( "UPS_off" ); + static const quality_id qual_BUTCHER( "BUTCHER" ); static const trait_id trait_CLAWS( "CLAWS" ); @@ -821,7 +827,7 @@ static int charges_of_internal( const T &self, const M &main, const itype_id &id } ); if( qty < limit && found_tool_with_UPS ) { - qty += main.charges_of( "UPS", limit - qty ); + qty += main.charges_of( itype_UPS, limit - qty ); if( visitor ) { visitor( qty ); } @@ -832,7 +838,7 @@ static int charges_of_internal( const T &self, const M &main, const itype_id &id /** @relates visitable */ template -int visitable::charges_of( const std::string &what, int limit, +int visitable::charges_of( const itype_id &what, int limit, const std::function &filter, std::function visitor ) const { @@ -841,14 +847,14 @@ int visitable::charges_of( const std::string &what, int limit, /** @relates visitable */ template <> -int visitable::charges_of( const std::string &what, int limit, +int visitable::charges_of( const itype_id &what, int limit, const std::function &filter, std::function visitor ) const { - if( what == "UPS" ) { + if( what == itype_UPS ) { int qty = 0; - qty = sum_no_wrap( qty, charges_of( "UPS_off" ) ); - qty = sum_no_wrap( qty, static_cast( charges_of( "adv_UPS_off" ) / 0.6 ) ); + qty = sum_no_wrap( qty, charges_of( itype_UPS_off ) ); + qty = sum_no_wrap( qty, static_cast( charges_of( itype_adv_UPS_off ) / 0.6 ) ); return std::min( qty, limit ); } const auto &binned = static_cast( this )->get_binned_items(); @@ -869,14 +875,14 @@ int visitable::charges_of( const std::string &what, int limit, /** @relates visitable */ template <> -int visitable::charges_of( const std::string &what, int limit, +int visitable::charges_of( const itype_id &what, int limit, const std::function &filter, std::function visitor ) const { auto self = static_cast( this ); auto p = dynamic_cast( self ); - if( what == "toolset" ) { + if( what == itype_toolset ) { if( p && p->has_active_bionic( bio_tools ) ) { return std::min( units::to_kilojoule( p->get_power_level() ), limit ); } else { @@ -884,10 +890,10 @@ int visitable::charges_of( const std::string &what, int limit, } } - if( what == "UPS" ) { + if( what == itype_UPS ) { int qty = 0; - qty = sum_no_wrap( qty, charges_of( "UPS_off" ) ); - qty = sum_no_wrap( qty, static_cast( charges_of( "adv_UPS_off" ) / 0.6 ) ); + qty = sum_no_wrap( qty, charges_of( itype_UPS_off ) ); + qty = sum_no_wrap( qty, static_cast( charges_of( itype_adv_UPS_off ) / 0.6 ) ); if( p && p->has_active_bionic( bio_ups ) ) { qty = sum_no_wrap( qty, units::to_kilojoule( p->get_power_level() ) ); } @@ -909,7 +915,7 @@ static int amount_of_internal( const T &self, const itype_id &id, bool pseudo, i { int qty = 0; self.visit_items( [&qty, &id, &pseudo, &limit, &filter]( const item * e ) { - if( ( id == "any" || e->typeId() == id ) && filter( *e ) && ( pseudo || + if( ( id.str() == "any" || e->typeId() == id ) && filter( *e ) && ( pseudo || !e->has_flag( "PSEUDO" ) ) ) { qty = sum_no_wrap( qty, 1 ); } @@ -920,7 +926,7 @@ static int amount_of_internal( const T &self, const itype_id &id, bool pseudo, i /** @relates visitable */ template -int visitable::amount_of( const std::string &what, bool pseudo, int limit, +int visitable::amount_of( const itype_id &what, bool pseudo, int limit, const std::function &filter ) const { return amount_of_internal( *this, what, pseudo, limit, filter ); @@ -928,17 +934,17 @@ int visitable::amount_of( const std::string &what, bool pseudo, int limit, /** @relates visitable */ template <> -int visitable::amount_of( const std::string &what, bool pseudo, int limit, +int visitable::amount_of( const itype_id &what, bool pseudo, int limit, const std::function &filter ) const { const auto &binned = static_cast( this )->get_binned_items(); const auto iter = binned.find( what ); - if( iter == binned.end() && what != "any" ) { + if( iter == binned.end() && what != itype_id( "any" ) ) { return 0; } int res = 0; - if( what == "any" ) { + if( what.str() == "any" ) { for( const auto &kv : binned ) { for( const item *it : kv.second ) { res = sum_no_wrap( res, it->amount_of( what, pseudo, limit, filter ) ); @@ -955,16 +961,16 @@ int visitable::amount_of( const std::string &what, bool pseudo, int l /** @relates visitable */ template <> -int visitable::amount_of( const std::string &what, bool pseudo, int limit, +int visitable::amount_of( const itype_id &what, bool pseudo, int limit, const std::function &filter ) const { auto self = static_cast( this ); - if( what == "toolset" && pseudo && self->has_active_bionic( bio_tools ) ) { + if( what == itype_toolset && pseudo && self->has_active_bionic( bio_tools ) ) { return 1; } - if( what == "apparatus" && pseudo ) { + if( what == itype_apparatus && pseudo ) { int qty = 0; visit_items( [&qty, &limit, &filter]( const item * e ) { if( e->get_quality( quality_id( "SMOKE_PIPE" ) ) >= 1 && filter( *e ) ) { @@ -980,7 +986,7 @@ int visitable::amount_of( const std::string &what, bool pseudo, int l /** @relates visitable */ template -bool visitable::has_amount( const std::string &what, int qty, bool pseudo, +bool visitable::has_amount( const itype_id &what, int qty, bool pseudo, const std::function &filter ) const { return amount_of( what, pseudo, qty, filter ) == qty; diff --git a/src/visitable.h b/src/visitable.h index 40210068901ad..1f6bb5aa1ef25 100644 --- a/src/visitable.h +++ b/src/visitable.h @@ -76,7 +76,7 @@ class visitable * @param filter only count charges of items that match the filter * @param visitor is called when UPS charge is used (parameter is the charge itself) */ - int charges_of( const std::string &what, int limit = INT_MAX, + int charges_of( const itype_id &what, int limit = INT_MAX, const std::function &filter = return_true, std::function visitor = nullptr ) const; @@ -88,12 +88,12 @@ class visitable * @param filter only count items that match the filter * @note items must be empty to be considered a match */ - int amount_of( const std::string &what, bool pseudo = true, + int amount_of( const itype_id &what, bool pseudo = true, int limit = INT_MAX, const std::function &filter = return_true ) const; /** Check instance provides at least qty of an item (@see amount_of) */ - bool has_amount( const std::string &what, int qty, bool pseudo = true, + bool has_amount( const itype_id &what, int qty, bool pseudo = true, const std::function &filter = return_true ) const; /** Returns all items (including those within a container) matching the filter */ diff --git a/src/weather.cpp b/src/weather.cpp index e264a8cd09df0..976d941de4646 100644 --- a/src/weather.cpp +++ b/src/weather.cpp @@ -42,6 +42,10 @@ static const efftype_id effect_glare( "glare" ); static const efftype_id effect_sleep( "sleep" ); static const efftype_id effect_snow_glare( "snow_glare" ); +static const itype_id itype_water( "water" ); +static const itype_id itype_water_acid( "water_acid" ); +static const itype_id itype_water_acid_weak( "water_acid_weak" ); + static const trait_id trait_CEPH_VISION( "CEPH_VISION" ); static const trait_id trait_FEATHERS( "FEATHERS" ); @@ -216,10 +220,10 @@ void item::add_rain_to_container( bool acid, int charges ) } put_in( ret, item_pocket::pocket_type::CONTAINER ); } else { - static const std::set allowed_liquid_types{ - "water", - "water_acid", - "water_acid_weak" + static const std::set allowed_liquid_types{ + itype_water, + itype_water_acid, + itype_water_acid_weak }; item *found_liq = contents.get_item_with( [&]( const item & liquid ) { return allowed_liquid_types.count( liquid.typeId() ); @@ -236,7 +240,7 @@ void item::add_rain_to_container( bool acid, int charges ) liq.charges += added; } - if( liq.typeId() == ret.typeId() || liq.typeId() == "water_acid_weak" ) { + if( liq.typeId() == ret.typeId() || liq.typeId() == itype_water_acid_weak ) { // The container already contains this liquid or weakly acidic water. // Don't do anything special -- we already added liquid. } else { @@ -253,7 +257,7 @@ void item::add_rain_to_container( bool acid, int charges ) if( transmute ) { liq = item( "water_acid_weak", calendar::turn, liq.charges ); - } else if( liq.typeId() == "water" ) { + } else if( liq.typeId() == itype_water ) { // The container has water, and the acid rain didn't turn it // into weak acid. Poison the water instead, assuming 1 // charge of acid would act like a charge of water with poison 5. diff --git a/src/wish.cpp b/src/wish.cpp index 1c1db3c10ddde..5bf790e519bfb 100644 --- a/src/wish.cpp +++ b/src/wish.cpp @@ -560,7 +560,7 @@ void debug_menu::wishitem( player *p, const tripoint &pos ) granted.item_tags.insert( cb.flag ); } // If the item has an ammunition, this loads it to capacity, including magazines. - if( granted.ammo_default() != "NULL" ) { + if( !granted.ammo_default().is_null() ) { granted.ammo_set( granted.ammo_default(), -1 ); } diff --git a/tests/archery_damage_test.cpp b/tests/archery_damage_test.cpp index 506340be7301e..a7837ffa77585 100644 --- a/tests/archery_damage_test.cpp +++ b/tests/archery_damage_test.cpp @@ -71,7 +71,7 @@ static void test_archery_balance( std::string weapon_type, std::string ammo_type { item weapon( weapon_type ); // The standard modern hunting arrow, make this a parameter if we extend to crossbows. - weapon.ammo_set( ammo_type, 1 ); + weapon.ammo_set( itype_id( ammo_type ), 1 ); projectile test_projectile; test_projectile.speed = 1000; diff --git a/tests/comestible_test.cpp b/tests/comestible_test.cpp index 07def3ae2e843..0b65a57f652db 100644 --- a/tests/comestible_test.cpp +++ b/tests/comestible_test.cpp @@ -29,7 +29,7 @@ static int comp_calories( const std::vector &components ) int calories = 0; for( item_comp it : components ) { const cata::value_ptr &temp = item::find_type( it.type )->comestible; - if( temp && temp->cooks_like.empty() ) { + if( temp && temp->cooks_like.is_empty() ) { calories += temp->default_nutrition.kcal * it.count; } else if( temp ) { const itype *cooks_like = item::find_type( temp->cooks_like ); diff --git a/tests/crafting_test.cpp b/tests/crafting_test.cpp index 4de95ae039234..69b3e47b64199 100644 --- a/tests/crafting_test.cpp +++ b/tests/crafting_test.cpp @@ -55,7 +55,7 @@ TEST_CASE( "recipe_subset" ) CHECK( std::find( cat_recipes.begin(), cat_recipes.end(), r ) != cat_recipes.end() ); } THEN( "it uses water" ) { - const auto comp_recipes( subset.of_component( "water" ) ); + const auto comp_recipes( subset.of_component( itype_id( "water" ) ) ); CHECK( comp_recipes.size() == 1 ); CHECK( std::find( comp_recipes.begin(), comp_recipes.end(), r ) != comp_recipes.end() ); @@ -372,8 +372,8 @@ TEST_CASE( "UPS shows as a crafting component", "[crafting][ups]" ) item &ups = dummy.i_add( item( "UPS_off", -1, 500 ) ); REQUIRE( dummy.has_item( ups ) ); REQUIRE( ups.charges == 500 ); - REQUIRE( dummy.charges_of( "UPS_off" ) == 500 ); - REQUIRE( dummy.charges_of( "UPS" ) == 500 ); + REQUIRE( dummy.charges_of( itype_id( "UPS_off" ) ) == 500 ); + REQUIRE( dummy.charges_of( itype_id( "UPS" ) ) == 500 ); } TEST_CASE( "tools use charge to craft", "[crafting][charge]" ) @@ -519,18 +519,20 @@ static void verify_inventory( const std::vector &has, std::ostringstream os; os << "Inventory:\n"; for( const item *i : g->u.inv_dump() ) { - os << " " << i->typeId() << " (" << i->charges << ")\n"; + os << " " << i->typeId().str() << " (" << i->charges << ")\n"; } os << "Wielded:\n" << g->u.weapon.tname() << "\n"; INFO( os.str() ); for( const std::string &i : has ) { INFO( "expecting " << i ); - const bool has_item = player_has_item_of_type( i ) || g->u.weapon.type->get_id() == i; + const bool has_item = + player_has_item_of_type( i ) || g->u.weapon.type->get_id() == itype_id( i ); REQUIRE( has_item ); } for( const std::string &i : hasnt ) { INFO( "not expecting " << i ); - const bool hasnt_item = !player_has_item_of_type( i ) && !( g->u.weapon.type->get_id() == i ); + const bool hasnt_item = + !player_has_item_of_type( i ) && !( g->u.weapon.type->get_id() == itype_id( i ) ); REQUIRE( hasnt_item ); } } diff --git a/tests/encumbrance_test.cpp b/tests/encumbrance_test.cpp index 76c2c979a62c1..5bc9edb3b478c 100644 --- a/tests/encumbrance_test.cpp +++ b/tests/encumbrance_test.cpp @@ -58,14 +58,14 @@ static void test_encumbrance_items( } static void test_encumbrance( - const std::vector &clothing_types, + const std::vector &clothing_types, const std::string &body_part, const int expected_encumbrance ) { CAPTURE( clothing_types ); std::vector clothing; - for( const itype_id &type : clothing_types ) { + for( const std::string &type : clothing_types ) { clothing.push_back( item( type ) ); } test_encumbrance_items( clothing, body_part, expected_encumbrance ); diff --git a/tests/event_test.cpp b/tests/event_test.cpp index 945dfb029094a..bf93fe557bfb9 100644 --- a/tests/event_test.cpp +++ b/tests/event_test.cpp @@ -11,8 +11,6 @@ #include "string_id.h" #include "type_id.h" -using itype_id = std::string; - TEST_CASE( "construct_event", "[event]" ) { cata::event e = cata::event::make( diff --git a/tests/invlet_test.cpp b/tests/invlet_test.cpp index 9ec46f19aab6a..ad5c28b9e433a 100644 --- a/tests/invlet_test.cpp +++ b/tests/invlet_test.cpp @@ -791,36 +791,36 @@ static void verify_invlet_consistency( const invlet_favorites &fav ) TEST_CASE( "invlet_favourites_can_erase", "[.invlet]" ) { invlet_favorites fav; - fav.set( 'a', "a" ); + fav.set( 'a', itype_id( "a" ) ); verify_invlet_consistency( fav ); - CHECK( fav.invlets_for( "a" ) == "a" ); + CHECK( fav.invlets_for( itype_id( "a" ) ) == "a" ); fav.erase( 'a' ); verify_invlet_consistency( fav ); - CHECK( fav.invlets_for( "a" ).empty() ); + CHECK( fav.invlets_for( itype_id( "a" ) ).empty() ); } TEST_CASE( "invlet_favourites_removes_clashing_on_insertion", "[.invlet]" ) { invlet_favorites fav; - fav.set( 'a', "a" ); + fav.set( 'a', itype_id( "a" ) ); verify_invlet_consistency( fav ); - CHECK( fav.invlets_for( "a" ) == "a" ); - CHECK( fav.invlets_for( "b" ).empty() ); - fav.set( 'a', "b" ); + CHECK( fav.invlets_for( itype_id( "a" ) ) == "a" ); + CHECK( fav.invlets_for( itype_id( "b" ) ).empty() ); + fav.set( 'a', itype_id( "b" ) ); verify_invlet_consistency( fav ); - CHECK( fav.invlets_for( "a" ).empty() ); - CHECK( fav.invlets_for( "b" ) == "a" ); + CHECK( fav.invlets_for( itype_id( "a" ) ).empty() ); + CHECK( fav.invlets_for( itype_id( "b" ) ) == "a" ); } TEST_CASE( "invlet_favourites_retains_order_on_insertion", "[.invlet]" ) { invlet_favorites fav; - fav.set( 'a', "a" ); - fav.set( 'b', "a" ); - fav.set( 'c', "a" ); + fav.set( 'a', itype_id( "a" ) ); + fav.set( 'b', itype_id( "a" ) ); + fav.set( 'c', itype_id( "a" ) ); verify_invlet_consistency( fav ); - CHECK( fav.invlets_for( "a" ) == "abc" ); - fav.set( 'b', "a" ); + CHECK( fav.invlets_for( itype_id( "a" ) ) == "abc" ); + fav.set( 'b', itype_id( "a" ) ); verify_invlet_consistency( fav ); - CHECK( fav.invlets_for( "a" ) == "abc" ); + CHECK( fav.invlets_for( itype_id( "a" ) ) == "abc" ); } diff --git a/tests/item_contents_test.cpp b/tests/item_contents_test.cpp index 14dd5e4aa91bf..6c74b339cfb14 100644 --- a/tests/item_contents_test.cpp +++ b/tests/item_contents_test.cpp @@ -42,7 +42,7 @@ TEST_CASE( "item_contents" ) CHECK( tool_belt.contents.num_item_stacks() == 4 ); tool_belt.contents.remove_items_if( []( item & it ) { - return it.typeId() == "hammer"; + return it.typeId() == itype_id( "hammer" ); } ); // check to see that removing an item works CHECK( tool_belt.contents.num_item_stacks() == 3 ); diff --git a/tests/item_group_test.cpp b/tests/item_group_test.cpp index 654b4a77723b7..2d5b7fa3baee7 100644 --- a/tests/item_group_test.cpp +++ b/tests/item_group_test.cpp @@ -1,6 +1,7 @@ #include "catch/catch.hpp" #include "item.h" #include "item_group.h" +#include "stringmaker.h" TEST_CASE( "spawn with default charges and with ammo", "[item_group]" ) { @@ -8,14 +9,14 @@ TEST_CASE( "spawn with default charges and with ammo", "[item_group]" ) default_charges.with_ammo = 100; SECTION( "tools without ammo" ) { item matches( "matches" ); - REQUIRE( matches.ammo_default() == "NULL" ); + REQUIRE( matches.ammo_default() == itype_id::NULL_ID() ); default_charges.modify( matches ); CHECK( matches.ammo_remaining() == matches.ammo_capacity() ); } SECTION( "gun with ammo type" ) { item glock( "glock_19" ); - REQUIRE( glock.ammo_default() != "NULL" ); + REQUIRE( !glock.ammo_default().is_null() ); default_charges.modify( glock ); CHECK( glock.ammo_remaining() == glock.ammo_capacity() ); } diff --git a/tests/item_location_test.cpp b/tests/item_location_test.cpp index 089b60eaebb9b..9ced2498ceb8b 100644 --- a/tests/item_location_test.cpp +++ b/tests/item_location_test.cpp @@ -30,7 +30,7 @@ TEST_CASE( "item_location_can_maintain_reference_despite_item_removal", "[item][ map_cursor cursor( pos ); item *tshirt = nullptr; cursor.visit_items( [&tshirt]( item * i ) { - if( i->typeId() == "tshirt" ) { + if( i->typeId() == itype_id( "tshirt" ) ) { tshirt = i; return VisitResponse::ABORT; } @@ -38,19 +38,19 @@ TEST_CASE( "item_location_can_maintain_reference_despite_item_removal", "[item][ } ); REQUIRE( tshirt != nullptr ); item_location item_loc( cursor, tshirt ); - REQUIRE( item_loc->typeId() == "tshirt" ); + REQUIRE( item_loc->typeId() == itype_id( "tshirt" ) ); for( int j = 0; j < 4; ++j ) { // Delete up to 4 random jeans map_stack stack = m.i_at( pos ); REQUIRE( !stack.empty() ); item *i = &random_entry_opt( stack )->get(); - if( i->typeId() == "jeans" ) { + if( i->typeId() == itype_id( "jeans" ) ) { m.i_rem( pos, i ); } } CAPTURE( m.i_at( pos ) ); REQUIRE( item_loc ); - CHECK( item_loc->typeId() == "tshirt" ); + CHECK( item_loc->typeId() == itype_id( "tshirt" ) ); } TEST_CASE( "item_location_doesnt_return_stale_map_item", "[item][item_location]" ) @@ -61,7 +61,7 @@ TEST_CASE( "item_location_doesnt_return_stale_map_item", "[item][item_location]" m.i_clear( pos ); m.add_item( pos, item( "tshirt" ) ); item_location item_loc( map_cursor( pos ), &m.i_at( pos ).only_item() ); - REQUIRE( item_loc->typeId() == "tshirt" ); + REQUIRE( item_loc->typeId() == itype_id( "tshirt" ) ); m.i_rem( pos, &*item_loc ); m.add_item( pos, item( "jeans" ) ); CHECK( !item_loc ); diff --git a/tests/item_test.cpp b/tests/item_test.cpp index 6eb133a788652..99d13b1f2f792 100644 --- a/tests/item_test.cpp +++ b/tests/item_test.cpp @@ -163,7 +163,7 @@ TEST_CASE( "stacking_over_time", "[item]" ) static void assert_minimum_length_to_volume_ratio( const item &target ) { - if( target.type->get_id() == "null" ) { + if( target.type->get_id().is_null() ) { return; } CAPTURE( target.type->get_id() ); diff --git a/tests/item_type_name_test.cpp b/tests/item_type_name_test.cpp index dab639d593474..b9807e66e6526 100644 --- a/tests/item_type_name_test.cpp +++ b/tests/item_type_name_test.cpp @@ -91,7 +91,7 @@ TEST_CASE( "blood item", "[item][type_name][blood]" ) item corpse = item::make_corpse( mon_zombie ); item blood( "blood" ); blood.set_mtype( corpse.get_mtype() ); - REQUIRE( blood.typeId() == "blood" ); + REQUIRE( blood.typeId() == itype_id( "blood" ) ); REQUIRE_FALSE( blood.is_corpse() ); CHECK( blood.type_name() == "zombie blood" ); @@ -101,7 +101,7 @@ TEST_CASE( "blood item", "[item][type_name][blood]" ) item corpse = item::make_corpse( mon_chicken ); item blood( "blood" ); blood.set_mtype( corpse.get_mtype() ); - REQUIRE( blood.typeId() == "blood" ); + REQUIRE( blood.typeId() == itype_id( "blood" ) ); REQUIRE_FALSE( blood.is_corpse() ); CHECK( blood.type_name() == "chicken blood" ); @@ -109,7 +109,7 @@ TEST_CASE( "blood item", "[item][type_name][blood]" ) SECTION( "blood from an unknown corpse" ) { item blood( "blood" ); - REQUIRE( blood.typeId() == "blood" ); + REQUIRE( blood.typeId() == itype_id( "blood" ) ); REQUIRE_FALSE( blood.is_corpse() ); CHECK( blood.type_name() == "human blood" ); diff --git a/tests/iteminfo_test.cpp b/tests/iteminfo_test.cpp index 0cc05a692a7a0..ddb3ef9ecb203 100644 --- a/tests/iteminfo_test.cpp +++ b/tests/iteminfo_test.cpp @@ -615,7 +615,7 @@ TEST_CASE( "show available recipes with item as an ingredient", "[item][iteminfo WHEN( "they have the recipe in a book, but not memorized" ) { item &textbook = g->u.i_add( item( "textbook_chemistry" ) ); g->u.do_read( textbook ); - REQUIRE( g->u.has_identified( "textbook_chemistry" ) ); + REQUIRE( g->u.has_identified( itype_id( "textbook_chemistry" ) ) ); // update the crafting inventory cache g->u.moves++; diff --git a/tests/iuse_actor_test.cpp b/tests/iuse_actor_test.cpp index ed73bf81068ee..46c7ee0de1855 100644 --- a/tests/iuse_actor_test.cpp +++ b/tests/iuse_actor_test.cpp @@ -58,7 +58,7 @@ TEST_CASE( "manhack", "[iuse_actor][manhack]" ) dummy.invoke_item( &test_item ); REQUIRE( !dummy.has_item_with( []( const item & it ) { - return it.typeId() == "bot_manhack"; + return it.typeId() == itype_id( "bot_manhack" ); } ) ); new_manhack = find_adjacent_monster( dummy.pos() ); diff --git a/tests/iuse_test.cpp b/tests/iuse_test.cpp index c4ff5ad5de59d..b063ffaeaa706 100644 --- a/tests/iuse_test.cpp +++ b/tests/iuse_test.cpp @@ -342,13 +342,13 @@ TEST_CASE( "towel", "[iuse][towel]" ) CHECK( dummy.body_wetness[bp_arm_r] == 0 ); AND_THEN( "the towel becomes wet" ) { - CHECK( towel.typeId() == "towel_wet" ); + CHECK( towel.typeId().str() == "towel_wet" ); } } } WHEN( "they use a wet towel" ) { - towel.convert( "towel_wet" ); + towel.convert( itype_id( "towel_wet" ) ); REQUIRE( towel.has_flag( flag_WET ) ); dummy.invoke_item( &towel ); @@ -366,7 +366,7 @@ TEST_CASE( "towel", "[iuse][towel]" ) REQUIRE( dummy.has_morale( MORALE_WET ) == -10 ); WHEN( "they use a wet towel" ) { - towel.convert( "towel_wet" ); + towel.convert( itype_id( "towel_wet" ) ); REQUIRE( towel.has_flag( flag_WET ) ); dummy.invoke_item( &towel ); @@ -383,7 +383,7 @@ TEST_CASE( "towel", "[iuse][towel]" ) CHECK( dummy.has_morale( MORALE_WET ) == 0 ); AND_THEN( "the towel becomes wet" ) { - CHECK( towel.typeId() == "towel_wet" ); + CHECK( towel.typeId() == itype_id( "towel_wet" ) ); } } } @@ -407,7 +407,7 @@ TEST_CASE( "towel", "[iuse][towel]" ) CHECK_FALSE( dummy.has_effect( efftype_id( "glowing" ) ) ); AND_THEN( "the towel becomes soiled" ) { - CHECK( towel.typeId() == "towel_soiled" ); + CHECK( towel.typeId() == itype_id( "towel_soiled" ) ); } } } @@ -427,7 +427,7 @@ TEST_CASE( "towel", "[iuse][towel]" ) CHECK( std::abs( dummy.has_morale( MORALE_WET ) ) ); AND_THEN( "the towel becomes soiled" ) { - CHECK( towel.typeId() == "towel_soiled" ); + CHECK( towel.typeId() == itype_id( "towel_soiled" ) ); } } } diff --git a/tests/magic_spell_effect_test.cpp b/tests/magic_spell_effect_test.cpp index b9943d12623bc..cc91d664e1d03 100644 --- a/tests/magic_spell_effect_test.cpp +++ b/tests/magic_spell_effect_test.cpp @@ -5,6 +5,7 @@ #include "magic.h" #include "magic_spell_effect_helpers.h" #include "npc.h" +#include "player_helpers.h" TEST_CASE( "line_attack", "[magic]" ) { @@ -31,7 +32,8 @@ TEST_CASE( "line_attack", "[magic]" ) spell sp( spell_id( "test_line_spell" ) ); // set up Character to test with, only need position - npc c; + npc &c = spawn_npc( point_zero, "test_talker" ); + clear_character( c ); c.setpos( tripoint_zero ); // target point 5 tiles east of zero diff --git a/tests/new_character_test.cpp b/tests/new_character_test.cpp index d89a377f6dd7f..38c9a90c1a600 100644 --- a/tests/new_character_test.cpp +++ b/tests/new_character_test.cpp @@ -184,7 +184,7 @@ TEST_CASE( "starting_items", "[slow]" ) std::stringstream failure_messages; for( const failure &f : failures ) { failure_messages << f.prof.c_str() << " " << f.mut << - " " << f.item_name << ": " << f.reason << "\n"; + " " << f.item_name.str() << ": " << f.reason << "\n"; } INFO( failure_messages.str() ); REQUIRE( failures.empty() ); diff --git a/tests/npc_talk_test.cpp b/tests/npc_talk_test.cpp index ba1bbdcdc2f9b..d63d1106f2c4d 100644 --- a/tests/npc_talk_test.cpp +++ b/tests/npc_talk_test.cpp @@ -570,7 +570,7 @@ TEST_CASE( "npc_talk_items", "[npc_talk]" ) g->u.remove_items_with( []( const item & it ) { return it.get_category().get_id() == item_category_id( "books" ) || it.get_category().get_id() == item_category_id( "food" ) || - it.typeId() == "bottle_glass"; + it.typeId() == itype_id( "bottle_glass" ); } ); d.add_topic( "TALK_TEST_HAS_ITEM" ); gen_response_lines( d, 1 ); @@ -684,24 +684,24 @@ TEST_CASE( "npc_talk_items", "[npc_talk]" ) CHECK( d.responses[5].text == "This is a u_has_item_category books test response." ); CHECK( d.responses[6].text == "This is a u_has_item_category books count 2 test response." ); CHECK( d.responses[0].text == "This is a repeated item manual_speech test response" ); - CHECK( d.responses[0].success.next_topic.item_type == "manual_speech" ); + CHECK( d.responses[0].success.next_topic.item_type == itype_id( "manual_speech" ) ); d.add_topic( "TALK_TEST_ITEM_REPEAT" ); gen_response_lines( d, 8 ); CHECK( d.responses[0].text == "This is a repeated category books, food test response" ); - CHECK( d.responses[0].success.next_topic.item_type == "beer" ); + CHECK( d.responses[0].success.next_topic.item_type == itype_id( "beer" ) ); CHECK( d.responses[1].text == "This is a repeated category books, food test response" ); - CHECK( d.responses[1].success.next_topic.item_type == "dnd_handbook" ); + CHECK( d.responses[1].success.next_topic.item_type == itype_id( "dnd_handbook" ) ); CHECK( d.responses[2].text == "This is a repeated category books, food test response" ); - CHECK( d.responses[2].success.next_topic.item_type == "manual_speech" ); + CHECK( d.responses[2].success.next_topic.item_type == itype_id( "manual_speech" ) ); CHECK( d.responses[3].text == "This is a repeated category books test response" ); - CHECK( d.responses[3].success.next_topic.item_type == "dnd_handbook" ); + CHECK( d.responses[3].success.next_topic.item_type == itype_id( "dnd_handbook" ) ); CHECK( d.responses[4].text == "This is a repeated category books test response" ); - CHECK( d.responses[4].success.next_topic.item_type == "manual_speech" ); + CHECK( d.responses[4].success.next_topic.item_type == itype_id( "manual_speech" ) ); CHECK( d.responses[5].text == "This is a repeated item beer, bottle_glass test response" ); - CHECK( d.responses[5].success.next_topic.item_type == "bottle_glass" ); + CHECK( d.responses[5].success.next_topic.item_type == itype_id( "bottle_glass" ) ); CHECK( d.responses[6].text == "This is a repeated item beer, bottle_glass test response" ); - CHECK( d.responses[6].success.next_topic.item_type == "beer" ); + CHECK( d.responses[6].success.next_topic.item_type == itype_id( "beer" ) ); CHECK( d.responses[7].text == "This is a basic test response." ); // test sell and consume @@ -710,7 +710,7 @@ TEST_CASE( "npc_talk_items", "[npc_talk]" ) REQUIRE( has_item( g->u, "bottle_plastic", 1 ) ); REQUIRE( has_beer_bottle( g->u, 2 ) ); const std::vector glass_bottles = g->u.items_with( []( const item & it ) { - return it.typeId() == "bottle_glass"; + return it.typeId() == itype_id( "bottle_glass" ); } ); REQUIRE( !glass_bottles.empty() ); REQUIRE( g->u.wield( *glass_bottles.front() ) ); diff --git a/tests/player_helpers.cpp b/tests/player_helpers.cpp index ab3d576424194..c0940e83159e7 100644 --- a/tests/player_helpers.cpp +++ b/tests/player_helpers.cpp @@ -29,7 +29,7 @@ int get_remaining_charges( const std::string &tool_id ) const inventory crafting_inv = g->u.crafting_inventory(); std::vector items = crafting_inv.items_with( [tool_id]( const item & i ) { - return i.typeId() == tool_id; + return i.typeId() == itype_id( tool_id ); } ); int remaining_charges = 0; for( const item *instance : items ) { @@ -42,7 +42,7 @@ bool player_has_item_of_type( const std::string &type ) { std::vector matching_items = g->u.inv.items_with( [&]( const item & i ) { - return i.type->get_id() == type; + return i.type->get_id() == itype_id( type ); } ); return !matching_items.empty(); @@ -162,18 +162,18 @@ void give_and_activate_bionic( player &p, bionic_id const &bioid ) if( bio.id->has_flag( "BIONIC_TOGGLED" ) && !bio.powered ) { const std::vector fuel_opts = bio.info().fuel_opts; if( !fuel_opts.empty() ) { - p.set_value( fuel_opts.front(), "2" ); + p.set_value( fuel_opts.front().str(), "2" ); } p.activate_bionic( bioindex ); INFO( "bionic " + bio.id.str() + " with index " + std::to_string( bioindex ) + " is active " ); REQUIRE( p.has_active_bionic( bioid ) ); if( !fuel_opts.empty() ) { - p.remove_value( fuel_opts.front() ); + p.remove_value( fuel_opts.front().str() ); } } } -item tool_with_ammo( const itype_id &tool, const int qty ) +item tool_with_ammo( const std::string &tool, const int qty ) { item tool_it( tool ); tool_it.ammo_set( tool_it.ammo_default(), qty ); diff --git a/tests/player_helpers.h b/tests/player_helpers.h index 136d1d937f411..09bcdc2abc48a 100644 --- a/tests/player_helpers.h +++ b/tests/player_helpers.h @@ -11,8 +11,6 @@ class npc; class player; struct point; -using itype_id = std::string; - int get_remaining_charges( const std::string &tool_id ); bool player_has_item_of_type( const std::string & ); void clear_character( player &, bool debug_storage = true ); @@ -22,6 +20,6 @@ void process_activity( player &dummy ); npc &spawn_npc( const point &, const std::string &npc_class ); void give_and_activate_bionic( player &, bionic_id const & ); -item tool_with_ammo( const itype_id &tool, int qty ); +item tool_with_ammo( const std::string &tool, int qty ); #endif // CATA_TESTS_PLAYER_HELPERS_H diff --git a/tests/projectile_test.cpp b/tests/projectile_test.cpp index 9c7b2731938de..38637fed0367c 100644 --- a/tests/projectile_test.cpp +++ b/tests/projectile_test.cpp @@ -50,7 +50,7 @@ TEST_CASE( "projectiles_through_obstacles", "[projectile]" ) // Create a gun to fire a projectile from item gun( itype_id( "m1a" ) ); - gun.ammo_set( "308", 5 ); + gun.ammo_set( itype_id( "308" ), 5 ); // Check that a bullet with the correct amount of speed can through obstacles CHECK( projectile_end_point( range, gun, 1000, 3 ) == range[2] ); diff --git a/tests/ranged_balance_test.cpp b/tests/ranged_balance_test.cpp index 2c91cd46807e1..8d2e32da264ca 100644 --- a/tests/ranged_balance_test.cpp +++ b/tests/ranged_balance_test.cpp @@ -77,11 +77,11 @@ static void arm_shooter( npc &shooter, const std::string &gun_type, const std::string &ammo_type = "" ) { shooter.remove_weapon(); - if( !shooter.is_wearing( "backpack" ) ) { + if( !shooter.is_wearing( itype_id( "backpack" ) ) ) { shooter.worn.push_back( item( "backpack" ) ); } - const itype_id &gun_id( gun_type ); + const itype_id &gun_id{ itype_id( gun_type ) }; // Give shooter a loaded gun of the requested type. item &gun = shooter.i_add( item( gun_id ) ); const itype_id ammo_id = ammo_type.empty() ? gun.ammo_default() : itype_id( ammo_type ); diff --git a/tests/reload_magazine_test.cpp b/tests/reload_magazine_test.cpp index 80ecd4b3f19be..f77fd71db0d5c 100644 --- a/tests/reload_magazine_test.cpp +++ b/tests/reload_magazine_test.cpp @@ -17,13 +17,13 @@ TEST_CASE( "reload_magazine", "[magazine] [visitable] [item] [item_location]" ) { - const itype_id gun_id = "m4a1"; + const itype_id gun_id( "m4a1" ); const ammotype gun_ammo( "223" ); - const itype_id ammo_id = "556"; // any type of compatible ammo - const itype_id alt_ammo = "223"; // any alternative type of compatible ammo - const itype_id bad_ammo = "9mm"; // any type of incompatible ammo - const itype_id mag_id = "stanag30"; // must be set to default magazine - const itype_id bad_mag = "glockmag"; // any incompatible magazine + const itype_id ammo_id( "556" ); // any type of compatible ammo + const itype_id alt_ammo( "223" ); // any alternative type of compatible ammo + const itype_id bad_ammo( "9mm" ); // any type of incompatible ammo + const itype_id mag_id( "stanag30" ); // must be set to default magazine + const itype_id bad_mag( "glockmag" ); // any incompatible magazine const int mag_cap = 30; CHECK( ammo_id != alt_ammo ); @@ -50,7 +50,7 @@ TEST_CASE( "reload_magazine", "[magazine] [visitable] [item] [item_location]" ) CHECK( p.can_reload( mag, bad_ammo ) == false ); CHECK( mag.ammo_types().count( gun_ammo ) ); CHECK( mag.ammo_capacity() == mag_cap ); - CHECK( mag.ammo_current() == "null" ); + CHECK( mag.ammo_current().is_null() ); CHECK( mag.ammo_data() == nullptr ); GIVEN( "An empty magazine" ) { @@ -184,7 +184,7 @@ TEST_CASE( "reload_magazine", "[magazine] [visitable] [item] [item_location]" ) CHECK( gun.ammo_types().count( gun_ammo ) ); CHECK( gun.ammo_capacity() == 0 ); CHECK( gun.ammo_remaining() == 0 ); - CHECK( gun.ammo_current() == "null" ); + CHECK( gun.ammo_current().is_null() ); CHECK( gun.ammo_data() == nullptr ); WHEN( "the gun is reloaded with an incompatible magazine" ) { @@ -214,7 +214,7 @@ TEST_CASE( "reload_magazine", "[magazine] [visitable] [item] [item_location]" ) REQUIRE( gun.ammo_capacity() == mag_cap ); } AND_THEN( "the gun contains no ammo" ) { - REQUIRE( gun.ammo_current() == "null" ); + REQUIRE( gun.ammo_current().is_null() ); REQUIRE( gun.ammo_remaining() == 0 ); REQUIRE( gun.ammo_data() == nullptr ); } diff --git a/tests/reloading_test.cpp b/tests/reloading_test.cpp index 96f4c77383e57..047c7b4d89b5f 100644 --- a/tests/reloading_test.cpp +++ b/tests/reloading_test.cpp @@ -96,7 +96,7 @@ TEST_CASE( "reload_gun_with_swappable_magazine", "[reload],[gun]" ) dummy.i_add( gun ); const std::vector guns = dummy.items_with( []( const item & it ) { - return it.typeId() == "glock_19"; + return it.typeId() == itype_id( "glock_19" ); } ); REQUIRE( guns.size() == 1 ); item &glock = *guns.front(); @@ -105,7 +105,7 @@ TEST_CASE( "reload_gun_with_swappable_magazine", "[reload],[gun]" ) item_location glock_loc( dummy, &glock ); REQUIRE( g->unload( glock_loc ) ); const std::vector glock_mags = dummy.items_with( []( const item & it ) { - return it.typeId() == "glockmag"; + return it.typeId() == itype_id( "glockmag" ); } ); REQUIRE( glock_mags.size() == 1 ); item &magazine = *glock_mags.front(); @@ -225,7 +225,7 @@ TEST_CASE( "automatic_reloading_action", "[reload],[gun]" ) THEN( "the associated magazine is reloaded" ) { const std::vector mags = dummy.items_with( []( const item & it ) { - return it.typeId() == "glockmag"; + return it.typeId() == itype_id( "glockmag" ); } ); REQUIRE( mags.size() == 1 ); REQUIRE( !mags.front()->contents.empty() ); @@ -261,7 +261,7 @@ TEST_CASE( "automatic_reloading_action", "[reload],[gun]" ) THEN( "the associated magazine is reloaded" ) { const std::vector mags = dummy.items_with( []( const item & it ) { - return it.typeId() == "glockmag"; + return it.typeId() == itype_id( "glockmag" ); } ); REQUIRE( mags.size() == 1 ); REQUIRE( !mags.front()->contents.empty() ); @@ -282,7 +282,7 @@ TEST_CASE( "automatic_reloading_action", "[reload],[gun]" ) THEN( "the second associated magazine is reloaded" ) { const std::vector mags = dummy.items_with( []( const item & it ) { - return it.typeId() == "glockbigmag"; + return it.typeId() == itype_id( "glockbigmag" ); } ); REQUIRE( mags.size() == 1 ); REQUIRE( !mags.front()->contents.empty() ); diff --git a/tests/requirements_test.cpp b/tests/requirements_test.cpp index 890e98235bd66..187a350fc5cfc 100644 --- a/tests/requirements_test.cpp +++ b/tests/requirements_test.cpp @@ -6,6 +6,13 @@ #include "catch/catch.hpp" +static const itype_id acid( "acid" ); +static const itype_id ash( "ash" ); +static const itype_id lye( "lye" ); +static const itype_id rock( "rock" ); +static const itype_id soap( "soap" ); +static const itype_id yarn( "yarn" ); + static void test_requirement_deduplication( const requirement_data::alter_item_comp_vector &before, std::vector after @@ -27,16 +34,16 @@ static void test_requirement_deduplication( TEST_CASE( "simple_requirements_dont_multiply", "[requirement]" ) { - test_requirement_deduplication( { { { "rock", 1 } } }, { { { { "rock", 1 } } } } ); + test_requirement_deduplication( { { { rock, 1 } } }, { { { { rock, 1 } } } } ); } TEST_CASE( "survivor_telescope_inspired_example", "[requirement]" ) { requirement_data::alter_item_comp_vector before; test_requirement_deduplication( - { { { "rock", 1 }, { "soap", 1 } }, { { "rock", 1 } } }, { - { { { "soap", 1 } }, { { "rock", 1 } } }, - { { { "rock", 2 } } } + { { { rock, 1 }, { soap, 1 } }, { { rock, 1 } } }, { + { { { soap, 1 } }, { { rock, 1 } } }, + { { { rock, 2 } } } } ); } @@ -44,9 +51,9 @@ TEST_CASE( "survivor_telescope_inspired_example_2", "[requirement]" ) { requirement_data::alter_item_comp_vector before; test_requirement_deduplication( - { { { "ash", 1 } }, { { "rock", 1 }, { "soap", 1 } }, { { "rock", 1 } }, { { "lye", 1 } } }, { - { { { "ash", 1 } }, { { "soap", 1 } }, { { "rock", 1 } }, { { "lye", 1 } } }, - { { { "ash", 1 } }, { { "rock", 2 } }, { { "lye", 1 } } } + { { { ash, 1 } }, { { rock, 1 }, { soap, 1 } }, { { rock, 1 } }, { { lye, 1 } } }, { + { { { ash, 1 } }, { { soap, 1 } }, { { rock, 1 } }, { { lye, 1 } } }, + { { { ash, 1 } }, { { rock, 2 } }, { { lye, 1 } } } } ); } @@ -54,10 +61,10 @@ TEST_CASE( "woods_soup_inspired_example", "[requirement]" ) { requirement_data::alter_item_comp_vector before; test_requirement_deduplication( - { { { "rock", 1 }, { "soap", 1 } }, { { "rock", 1 }, { "yarn", 1 } } }, { - { { { "soap", 1 } }, { { "rock", 1 }, { "yarn", 1 } } }, - { { { "rock", 1 } }, { { "yarn", 1 } } }, - { { { "rock", 2 } } } + { { { rock, 1 }, { soap, 1 } }, { { rock, 1 }, { yarn, 1 } } }, { + { { { soap, 1 } }, { { rock, 1 }, { yarn, 1 } } }, + { { { rock, 1 } }, { { yarn, 1 } } }, + { { { rock, 2 } } } } ); } @@ -65,12 +72,12 @@ TEST_CASE( "triple_overlap_1", "[requirement]" ) { requirement_data::alter_item_comp_vector before; test_requirement_deduplication( { - { { "rock", 1 }, { "soap", 1 } }, - { { "rock", 1 } }, - { { "soap", 1 } } + { { rock, 1 }, { soap, 1 } }, + { { rock, 1 } }, + { { soap, 1 } } }, { - { { { "rock", 1 } }, { { "soap", 2 } } }, - { { { "rock", 2 } }, { { "soap", 1 } } }, + { { { rock, 1 } }, { { soap, 2 } } }, + { { { rock, 2 } }, { { soap, 1 } } }, } ); } @@ -78,14 +85,14 @@ TEST_CASE( "triple_overlap_2", "[requirement]" ) { requirement_data::alter_item_comp_vector before; test_requirement_deduplication( { - { { "rock", 1 }, { "soap", 1 } }, - { { "rock", 1 }, { "yarn", 1 } }, - { { "soap", 1 }, { "acid", 1 } } + { { rock, 1 }, { soap, 1 } }, + { { rock, 1 }, { yarn, 1 } }, + { { soap, 1 }, { acid, 1 } } }, { - { { { "soap", 1 } }, { { "rock", 1 }, { "yarn", 1 } }, { { "acid", 1 } } }, - { { { "rock", 1 }, { "yarn", 1 } }, { { "soap", 2 } } }, - { { { "rock", 1 } }, { { "yarn", 1 } }, { { "acid", 1 }, { "soap", 1 } } }, - { { { "rock", 2 } }, { { "acid", 1 }, { "soap", 1 } } }, + { { { soap, 1 } }, { { rock, 1 }, { yarn, 1 } }, { { acid, 1 } } }, + { { { rock, 1 }, { yarn, 1 } }, { { soap, 2 } } }, + { { { rock, 1 } }, { { yarn, 1 } }, { { acid, 1 }, { soap, 1 } } }, + { { { rock, 2 } }, { { acid, 1 }, { soap, 1 } } }, } ); } @@ -93,20 +100,20 @@ TEST_CASE( "triple_overlap_3", "[requirement]" ) { requirement_data::alter_item_comp_vector before; test_requirement_deduplication( { - { { "rock", 1 }, { "soap", 1 } }, - { { "rock", 1 }, { "yarn", 1 } }, - { { "soap", 1 }, { "yarn", 1 } } + { { rock, 1 }, { soap, 1 } }, + { { rock, 1 }, { yarn, 1 } }, + { { soap, 1 }, { yarn, 1 } } }, { // These results are not ideal. Two of them are equivalent and // another two could be merged. But they are correct, and that // seems good enough for now. I don't anticipate any real recipes // being as complicated to resolve as this one. - { { { "soap", 1 } }, { { "rock", 1 } }, { { "yarn", 1 } } }, - { { { "soap", 1 } }, { { "yarn", 2 } } }, - { { { "rock", 1 }, { "yarn", 1 } }, { { "soap", 2 } } }, - { { { "rock", 1 } }, { { "yarn", 1 } }, { { "soap", 1 } } }, - { { { "rock", 1 } }, { { "yarn", 2 } } }, - { { { "rock", 2 } }, { { "yarn", 1 }, { "soap", 1 } } }, + { { { soap, 1 } }, { { rock, 1 } }, { { yarn, 1 } } }, + { { { soap, 1 } }, { { yarn, 2 } } }, + { { { rock, 1 }, { yarn, 1 } }, { { soap, 2 } } }, + { { { rock, 1 } }, { { yarn, 1 } }, { { soap, 1 } } }, + { { { rock, 1 } }, { { yarn, 2 } } }, + { { { rock, 2 } }, { { yarn, 1 }, { soap, 1 } } }, } ); } @@ -114,8 +121,8 @@ TEST_CASE( "deduplicate_repeated_requirements", "[requirement]" ) { requirement_data::alter_item_comp_vector before; test_requirement_deduplication( { - { { "rock", 1 } }, { { "yarn", 1 } }, { { "rock", 1 } }, { { "yarn", 1 } } + { { rock, 1 } }, { { yarn, 1 } }, { { rock, 1 } }, { { yarn, 1 } } }, { - { { { "rock", 2 } }, { { "yarn", 2 } } }, + { { { rock, 2 } }, { { yarn, 2 } } }, } ); } diff --git a/tests/stringmaker.h b/tests/stringmaker.h index 909ab22089c58..f65d7fc3c2450 100644 --- a/tests/stringmaker.h +++ b/tests/stringmaker.h @@ -12,10 +12,17 @@ namespace Catch { +template +struct StringMaker> { + static std::string convert( const string_id &i ) { + return string_format( "string_id( \"%s\" )", i.str() ); + } +}; + template<> struct StringMaker { static std::string convert( const item &i ) { - return string_format( "item( \"%s\" )", i.typeId() ); + return string_format( "item( itype_id( \"%s\" ) )", i.typeId().str() ); } }; diff --git a/tests/vehicle_efficiency_test.cpp b/tests/vehicle_efficiency_test.cpp index c58b9f4188f2f..c56cca8250b85 100644 --- a/tests/vehicle_efficiency_test.cpp +++ b/tests/vehicle_efficiency_test.cpp @@ -70,11 +70,11 @@ static std::map set_vehicle_fuel( vehicle &v, const float veh_fue } // We ignore battery when setting fuel because it uses designated "tanks" - actually_used.erase( "battery" ); + actually_used.erase( itype_id( "battery" ) ); // Currently only one liquid fuel supported REQUIRE( actually_used.size() <= 1 ); - itype_id liquid_fuel = "null"; + itype_id liquid_fuel = itype_id::NULL_ID(); for( const auto &ft : actually_used ) { if( item::find_type( ft )->phase == LIQUID ) { liquid_fuel = ft; @@ -89,9 +89,9 @@ static std::map set_vehicle_fuel( vehicle &v, const float veh_fue vehicle_part &pt = vp.part(); if( pt.is_battery() ) { - pt.ammo_set( "battery", pt.ammo_capacity() * veh_fuel_mult ); - ret[ "battery" ] += pt.ammo_capacity() * veh_fuel_mult; - } else if( pt.is_tank() && liquid_fuel != "null" ) { + pt.ammo_set( itype_id( "battery" ), pt.ammo_capacity() * veh_fuel_mult ); + ret[ itype_id( "battery" ) ] += pt.ammo_capacity() * veh_fuel_mult; + } else if( pt.is_tank() && !liquid_fuel.is_null() ) { float qty = pt.ammo_capacity() * veh_fuel_mult; qty *= std::max( item::find_type( liquid_fuel )->stack_size, 1 ); qty /= to_milliliter( units::legacy_volume_factor ); @@ -103,7 +103,7 @@ static std::map set_vehicle_fuel( vehicle &v, const float veh_fue } // We re-add battery because we want it accounted for, just not in the section above - actually_used.insert( "battery" ); + actually_used.insert( itype_id( "battery" ) ); for( auto iter = ret.begin(); iter != ret.end(); ) { if( iter->second <= 0 || actually_used.count( iter->first ) == 0 ) { iter = ret.erase( iter ); @@ -124,11 +124,11 @@ static float fuel_percentage_left( vehicle &v, const std::map &st vehicle_part &pt = vp.part(); if( ( pt.is_battery() || pt.is_reactor() || pt.is_tank() ) && - pt.ammo_current() != "null" ) { + !pt.ammo_current().is_null() ) { fuel_amount[ pt.ammo_current() ] += pt.ammo_remaining(); } - if( pt.is_engine() && pt.info().fuel_type != "null" ) { + if( pt.is_engine() && !pt.info().fuel_type.is_null() ) { consumed_fuels.insert( pt.info().fuel_type ); } } diff --git a/tests/vehicle_turrets_test.cpp b/tests/vehicle_turrets_test.cpp index 4927d9145bf9d..25b7e5e92b93c 100644 --- a/tests/vehicle_turrets_test.cpp +++ b/tests/vehicle_turrets_test.cpp @@ -72,7 +72,8 @@ TEST_CASE( "vehicle_turret", "[vehicle] [gun] [magazine] [.]" ) REQUIRE( veh->install_part( point_zero, vpart_id( "storage_battery" ), true ) >= 0 ); veh->charge_battery( 10000 ); - auto ammo = ammotype( veh->turret_query( veh->parts[idx] ).base()->ammo_default() ); + auto ammo = + ammotype( veh->turret_query( veh->parts[idx] ).base()->ammo_default().str() ); if( veh->part_flag( idx, "USE_TANKS" ) ) { auto *tank = biggest_tank( ammo ); diff --git a/tests/visitable_remove_test.cpp b/tests/visitable_remove_test.cpp index 324bbc172abf4..696208e169996 100644 --- a/tests/visitable_remove_test.cpp +++ b/tests/visitable_remove_test.cpp @@ -38,9 +38,9 @@ static int count_items( const T &src, const itype_id &id ) TEST_CASE( "visitable_remove", "[visitable]" ) { - const std::string liquid_id = "water"; - const std::string container_id = "bottle_plastic"; - const std::string worn_id = "flask_hip"; + const itype_id liquid_id( "water" ); + const itype_id container_id( "bottle_plastic" ); + const itype_id worn_id( "flask_hip" ); const int count = 5; REQUIRE( item( container_id ).is_container() ); @@ -499,10 +499,10 @@ TEST_CASE( "inventory_remove_invalidates_binning_cache", "[visitable][inventory] inventory inv; std::list items = { item( "bone" ) }; inv += items; - CHECK( inv.charges_of( "bone" ) == 1 ); + CHECK( inv.charges_of( itype_id( "bone" ) ) == 1 ); inv.remove_items_with( return_true ); CHECK( inv.size() == 0 ); // The following used to be a heap use-after-free due to a caching bug. // Now should be safe. - CHECK( inv.charges_of( "bone" ) == 0 ); + CHECK( inv.charges_of( itype_id( "bone" ) ) == 0 ); } diff --git a/tests/visitable_test.cpp b/tests/visitable_test.cpp index bd72d18afb0f9..eea64b80f3042 100644 --- a/tests/visitable_test.cpp +++ b/tests/visitable_test.cpp @@ -16,5 +16,5 @@ TEST_CASE( "visitable_summation" ) const item unlimited_water( "water", 0, item::INFINITE_CHARGES ); test_inv.add_item( unlimited_water ); - CHECK( test_inv.charges_of( "water", item::INFINITE_CHARGES ) > 1 ); + CHECK( test_inv.charges_of( itype_id( "water" ), item::INFINITE_CHARGES ) > 1 ); } diff --git a/tests/wield_times_test.cpp b/tests/wield_times_test.cpp index b25866a0e8436..a1fcebdaacc99 100644 --- a/tests/wield_times_test.cpp +++ b/tests/wield_times_test.cpp @@ -86,13 +86,13 @@ TEST_CASE( "Wield time test", "[wield]" ) avatar guy; clear_character( guy ); - wield_check_from_inv( guy, "halberd", 612 ); + wield_check_from_inv( guy, itype_id( "halberd" ), 612 ); clear_character( guy ); - wield_check_from_inv( guy, "aspirin", 375 ); + wield_check_from_inv( guy, itype_id( "aspirin" ), 375 ); clear_character( guy ); - wield_check_from_inv( guy, "knife_combat", 412 ); + wield_check_from_inv( guy, itype_id( "knife_combat" ), 412 ); clear_character( guy ); - wield_check_from_ground( guy, "metal_tank", 300 ); + wield_check_from_ground( guy, itype_id( "metal_tank" ), 300 ); clear_character( guy ); } }