Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix: Molotov Fix/Rework, make turn_per_charge less inconsistent. #5480

Merged
merged 11 commits into from
Oct 2, 2024
2 changes: 1 addition & 1 deletion data/json/item_actions.json
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@
{
"type": "item_action",
"id": "MOLOTOV_LIT",
"name": { "str": "Light up" }
"name": { "str": "Detonate" }
},
{
"type": "item_action",
Expand Down
2 changes: 0 additions & 2 deletions data/json/items/generic/toys_and_sports.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"color": "pink",
"ammo": "battery",
"charges_per_use": 1,
"turns_per_charge": 20,
"use_action": "DOLLCHAT",
"magazines": [
[
Expand Down Expand Up @@ -47,7 +46,6 @@
"color": "pink",
"ammo": "battery",
"charges_per_use": 1,
"turns_per_charge": 20,
"use_action": "DOLLCHAT",
"magazines": [
[
Expand Down
8 changes: 4 additions & 4 deletions data/json/items/tool/explosives.json
Original file line number Diff line number Diff line change
Expand Up @@ -988,8 +988,6 @@
"material": [ "glass", "cotton" ],
"symbol": "*",
"color": "light_gray",
"initial_charges": 1,
"max_charges": 1,
"use_action": {
"target": "molotov_lit",
"msg": "You light the Molotov cocktail!",
Expand All @@ -1007,7 +1005,7 @@
"type": "TOOL",
"category": "weapons",
"name": { "str": "Molotov cocktail" },
"description": "A bottle of flammable liquid with a flaming rag stoppered in its neck. Throwing it will shatter the bottle on impact and ignite a fireball. Dropping it will set you on fire, so don't do that unless you want to burn to death.",
"description": "A bottle of flammable liquid with a flaming rag stoppered in its neck. Throwing it will shatter the bottle on impact and ignite a fireball. You can also activate it to smash it on yourself, but why would you want to do that?",
"weight": "742 g",
"volume": "750 ml",
"price": "0 cent",
Expand All @@ -1019,8 +1017,10 @@
"color": "light_gray",
"initial_charges": 1,
"max_charges": 1,
"turns_per_charge": 1,
"turns_per_charge": 5,
"use_action": "MOLOTOV_LIT",
"revert_to": "molotov",
"revert_msg": "Your lit molotov goes out.",
"flags": [ "LIGHT_20", "TRADER_AVOID", "NPC_THROW_NOW", "NO_REPAIR", "WATER_EXTINGUISH", "ACT_ON_RANGED_HIT" ]
},
{
Expand Down
40 changes: 24 additions & 16 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,9 @@ void item::deactivate()
}

active = false;
if( is_tool() ) {
type->tool->turns_active = 0;
}

// Is not placed in the world, so either a template of some kind or a temporary item.
if( !has_position() ) {
Expand Down Expand Up @@ -9906,32 +9909,37 @@ detached_ptr<item> item::process_tool( detached_ptr<item> &&self, player *carrie
int energy = 0;
const bool uses_UPS = self->has_flag( flag_USE_UPS );
bool revert_destroy = false;
if( self->type->tool->turns_per_charge > 0 &&
to_turn<int>( calendar::turn ) % self->type->tool->turns_per_charge == 0 ) {
energy = std::max( self->ammo_required(), 1 );

if( self->type->tool->turns_per_charge > 0 ) {
if( self->type->tool->turns_active >= self->type->tool->turns_per_charge ) {
energy = std::max( self->ammo_required(), 1 );
self->type->tool->turns_active = 0;
}
self->type->tool->turns_active += 1;
} else if( self->type->tool->power_draw > 0 ) {
// power_draw in mW / 1000000 to give kJ (battery unit) per second
energy = self->type->tool->power_draw / 1000000;
// energy_bat remainder results in chance at additional charge/discharge
energy += x_in_y( self->type->tool->power_draw % 1000000, 1000000 ) ? 1 : 0;
}

// If energy is 0 we just skip over this and go to tick processing.
if( energy ) {
energy -= self->ammo_consume( energy, pos );
// If ammo_required is 0 we just skip over this and go to tick processing.
if( energy || self->ammo_required() > 0 ) {
// No need to look for charges if energy is 0
if( energy ) {
energy -= self->ammo_consume( energy, pos );

// for power armor pieces, try to use power armor interface first.
if( carrier && self->is_power_armor() && character_funcs::can_interface_armor( *carrier ) ) {
if( carrier->use_charges_if_avail( itype_bio_armor, energy ) ) {
energy = 0;
// for power armor pieces, try to use power armor interface first.
if( carrier && self->is_power_armor() && character_funcs::can_interface_armor( *carrier ) ) {
if( carrier->use_charges_if_avail( itype_bio_armor, energy ) ) {
energy = 0;
}
}
}

// for items in player possession if insufficient charges within tool try UPS
if( carrier && uses_UPS ) {
if( carrier->use_charges_if_avail( itype_UPS, energy ) ) {
energy = 0;
// for items in player possession if insufficient charges within tool try UPS
if( carrier && uses_UPS ) {
if( carrier->use_charges_if_avail( itype_UPS, energy ) ) {
energy = 0;
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/itype.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ struct islot_tool {
int charge_factor = 1;
int charges_per_use = 0;
int turns_per_charge = 0;
int turns_active = 0;
int power_draw = 0;

std::vector<int> rand_charges;
Expand Down
23 changes: 11 additions & 12 deletions src/iuse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,6 @@ static const itype_id itype_joint( "joint" );
static const itype_id itype_log( "log" );
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" );
Expand Down Expand Up @@ -3751,6 +3750,12 @@ int iuse::molotov_lit( player *p, item *it, bool t, const tripoint &pos )
if( pos.x == -999 || pos.y == -999 ) {
return 0;
} else if( !t ) {
if( p->has_item( *it ) ) {
if( !query_yn( "Really smash it on yourself?" ) ) {
p->add_msg_if_player( m_info, _( "You should probably throw it instead." ) );
return 0;
}
}
for( const tripoint &pt : g->m.points_in_radius( pos, 1, 0 ) ) {
const int intensity = 1 + one_in( 3 ) + one_in( 5 );
g->m.add_field( pt, fd_fire, intensity );
Expand All @@ -3760,18 +3765,12 @@ int iuse::molotov_lit( player *p, item *it, bool t, const tripoint &pos )
p->rem_morale( MORALE_PYROMANIA_NOFIRE );
p->add_msg_if_player( m_good, _( "Fire… Good…" ) );
}
// If you exploded it on yourself through activation.
if( it->has_position() ) {
it->detach();
}
return 1;
} else if( it->charges > 0 ) {
p->add_msg_if_player( m_info, _( "You've already lit the %s, try throwing it instead." ),
it->tname() );
return 0;
} else if( p->has_item( *it ) && it->charges == 0 ) {
it->charges += 1;
if( one_in( 5 ) ) {
p->add_msg_if_player( _( "Your lit Molotov goes out." ) );
it->convert( itype_molotov );
it->deactivate();
}
return 0;
}
return 0;
Expand Down Expand Up @@ -7737,7 +7736,7 @@ int iuse::foodperson( player *p, item *it, bool t, const tripoint &pos )
}

time_duration shift = time_duration::from_turns( it->magazine_current()->ammo_remaining() *
it->type->tool->turns_per_charge );
it->type->tool->turns_per_charge - it->type->tool->turns_active );

p->add_msg_if_player( m_info, _( "Your HUD lights-up: \"Your shift ends in %s\"." ),
to_string( shift ) );
Expand Down
8 changes: 8 additions & 0 deletions src/iuse_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,14 @@ void explosion_iuse::trigger_explosion( const tripoint &pos, Creature *source )
const int field_intensity = rng( fields_min_intensity, fields_max_intensity );
here.add_field( gas_source, fields_type, field_intensity, 1_turns );
}
if( source == &get_player_character() && source->has_trait( trait_PYROMANIA ) ) {
if( fields_type == fd_fire || fd_incendiary ) {
Character &p = get_player_character();
p.add_morale( MORALE_PYROMANIA_STARTFIRE, 15, 15, 8_hours, 6_hours );
p.rem_morale( MORALE_PYROMANIA_NOFIRE );
p.add_msg_if_player( m_good, _( "Fire… Good…" ) );
}
}
}
if( scrambler_blast_radius >= 0 ) {
for( const tripoint &dest : here.points_in_radius( pos, scrambler_blast_radius ) ) {
Expand Down
4 changes: 4 additions & 0 deletions src/savegame_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2183,6 +2183,9 @@ void item::io( Archive &archive )
archive.io( "invlet", invlet, '\0' );
archive.io( "damaged", damage_, 0 );
archive.io( "active", active, false );
if( is_tool() ) {
archive.io( "turns_active", type->tool->turns_active, 0 );
}
archive.io( "is_favorite", is_favorite, false );
archive.io( "item_counter", item_counter, static_cast<decltype( item_counter )>( 0 ) );
archive.io( "rot", rot, 0_turns );
Expand Down Expand Up @@ -2303,6 +2306,7 @@ void item::io( Archive &archive )
debugmsg( "Item %s was loaded with charges, but can not have any!", type->get_id() );
}
charges = 0;
curammo = nullptr;
}

// Relic check. Kinda late, but that's how relics have to be
Expand Down
Loading