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

Properly move pulping to activity actor, tweak it #79483

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions data/json/monsters/monster_flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -643,5 +643,11 @@
"id": "TEEP_IMMUNE",
"type": "monster_flag",
"//": "Immune to telepathic damage/detection"
},
{
"id": "PULP_PRYING",
"type": "monster_flag",
"//": "This monster has a great armor, and it is much harder to pulp it without a proper tool",
"//2": "Rule of thumb: if monster has something like a spine character wants to break, and it is covered by any armor, use this flag"
}
]
2 changes: 1 addition & 1 deletion data/json/player_activities.json
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@
"type": "activity_type",
"activity_level": "EXTRA_EXERCISE",
"verb": "smashing",
"based_on": "neither",
"based_on": "speed",
GuardianDll marked this conversation as resolved.
Show resolved Hide resolved
"can_resume": false
},
{
Expand Down
359 changes: 271 additions & 88 deletions src/activity_actor.cpp

Large diffs are not rendered by default.

51 changes: 39 additions & 12 deletions src/activity_actor_definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -2407,36 +2407,63 @@ class pulp_activity_actor : public activity_actor
{
public:
pulp_activity_actor() = default;
explicit pulp_activity_actor( const tripoint_abs_ms placement,
const bool pulp_acid = false ) : placement( { placement } ),
num_corpses( 0 ), pulp_acid( pulp_acid ) {}
explicit pulp_activity_actor( const std::set<tripoint_abs_ms> &placement,
const bool pulp_acid = false ) : placement( placement ), num_corpses( 0 ), pulp_acid( pulp_acid ) {}
explicit pulp_activity_actor( const tripoint_abs_ms placement ) : placement( { placement } ),
num_corpses( 0 ), pulp_power( 0 ), pulp_effort( 0 ), mess_radius( 1 ) {}
explicit pulp_activity_actor( const std::set<tripoint_abs_ms> &placement ) : placement( placement ),
num_corpses( 0 ), pulp_power( 0 ), pulp_effort( 0 ), mess_radius( 1 ) {}
const activity_id &get_type() const override {
static const activity_id ACT_PULP( "ACT_PULP" );
return ACT_PULP;
}

void start( player_activity &act, Character &who ) override;
void do_turn( player_activity &act, Character &you ) override;
bool punch_corpse_once( item &corpse, player_activity &act, Character &you, tripoint_bub_ms pos,
map &here );
// void canceled( player_activity &act, Character &p ) override;
void finish( player_activity &, Character & ) override;

void send_final_message( Character &you ) const;

std::unique_ptr<activity_actor> clone() const override {
return std::make_unique<pulp_activity_actor>( *this );
auto plp = std::make_unique<pulp_activity_actor>( *this );
plp.get()->current_pos_iter = plp.get()->placement.begin();
return plp;
}

void serialize( JsonOut &jsout ) const override;
static std::unique_ptr<activity_actor> deserialize( JsonValue &jsin );

private:
bool can_resume_with_internal( const activity_actor &other,
const Character &/*who*/ ) const override {
const pulp_activity_actor &actor = static_cast<const pulp_activity_actor &>( other );
return actor.pulp_acid == pulp_acid;
}
// tripoints with corpses we need to pulp;
// either single tripoint shoved into set, or 3x3 zone around u/npc
std::set<tripoint_abs_ms> placement;

int unpulped_corpses_qty = 0;
// for tanky monsters
bool can_pry_armor = false;

double bash_factor;
// bools for end message
bool stomps_only = false;
bool weapon_only = false;
bool can_severe_cutting = false;
bool used_pry = false;
bool couldnt_use_pry = false;
bool too_big_corpse = false;
std::string bash_tool;
std::string cut_tool;
std::string pry_tool;
// how many corpses we pulped
int num_corpses;
bool pulp_acid;
// how much damage you deal to corpse every second, average of multiple values
float pulp_power;
// how much stamina is consumed after each punch
float pulp_effort;
// how far the splatter goes
int mess_radius;
// what `placement` we are currently at
std::set<tripoint_abs_ms>::const_iterator current_pos_iter;
};

class wait_stamina_activity_actor : public activity_actor
Expand Down
38 changes: 38 additions & 0 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9681,6 +9681,44 @@ bool Character::use_charges_if_avail( const itype_id &it, int quantity )
return false;
}

std::pair<float, item> Character::get_best_weapon_by_damage_type( const damage_type_id dmg_type )
const
{
std::pair<float, item> best_weapon = std::make_pair( 0, item() );

cache_visit_items_with( "best_damage", &item::is_melee, [&best_weapon, this,
dmg_type]( const item & it ) {
damage_instance di;
roll_damage( dmg_type, false, di, true, it, attack_vector_id::NULL_ID(),
sub_bodypart_str_id::NULL_ID(), 1.f );
for( damage_unit du : di.damage_units ) {
if( du.type == dmg_type && best_weapon.first < du.amount ) {
best_weapon = std::make_pair( du.amount, it );
}
}
} );

return best_weapon;
}

std::pair<int, item> Character::get_best_tool( const quality_id quality ) const
{
// todo: check edge case of you having bionic tool/mutation,
// something that max_quality() is aware but max_quality() is not?
std::pair<int, item> best_tool = std::make_pair( 0, item() );

cache_visit_items_with( "best_quality", &item::is_tool, [&best_tool, this,
quality]( const item & it ) {
int max_qlty = max_quality( quality );
if( it.get_quality( quality ) == max_qlty ) {
best_tool = std::make_pair( max_qlty, it );
return;
}
} );

return best_tool;
}

units::energy Character::available_ups() const
{
units::energy available_charges = 0_kJ;
Expand Down
4 changes: 4 additions & 0 deletions src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -2968,6 +2968,10 @@ class Character : public Creature, public visitable
// Uses up charges
bool use_charges_if_avail( const itype_id &it, int quantity );

std::pair<float, item> get_best_weapon_by_damage_type( const damage_type_id dmg_type ) const;

std::pair<int, item> get_best_tool( const quality_id quality ) const;

/**
* Available ups from all sources
* Sum of mech, bionic UPS and UPS
Expand Down
18 changes: 3 additions & 15 deletions src/handle_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -903,12 +903,6 @@ static void haul_toggle()
get_avatar().toggle_hauling();
}

static bool is_smashable_corpse( const item &maybe_corpse )
{
return maybe_corpse.is_corpse() && maybe_corpse.damage() < maybe_corpse.max_damage() &&
maybe_corpse.can_revive();
}

static void smash()
{
const bool allow_floor_bash = debug_mode; // Should later become "true"
Expand All @@ -923,7 +917,7 @@ static void smash()
// terrain smashing unless it's actually possible.
bool smashable_corpse_at_target = false;
for( const item &maybe_corpse : get_map().i_at( smashp ) ) {
if( is_smashable_corpse( maybe_corpse ) ) {
if( maybe_corpse.can_revive() ) {
smashable_corpse_at_target = true;
break;
}
Expand Down Expand Up @@ -1022,19 +1016,13 @@ avatar::smash_result avatar::smash( tripoint_bub_ms &smashp )

bool should_pulp = false;
for( const item &maybe_corpse : here.i_at( smashp ) ) {
if( is_smashable_corpse( maybe_corpse ) ) {
if( maybe_corpse.get_mtype()->bloodType()->has_acid &&
!is_immune_field( fd_acid ) ) {
if( !query_yn( _( "Are you sure you want to pulp an acid filled corpse?" ) ) ) {
return ret; // Player doesn't want an acid bath
}
}
if( maybe_corpse.can_revive() ) {
should_pulp = true; // There is at least one corpse to pulp
}
}

if( should_pulp ) {
assign_activity( pulp_activity_actor( here.get_abs( smashp ), true ) );
assign_activity( pulp_activity_actor( here.get_abs( smashp ) ) );
return ret; // don't smash terrain if we've smashed a corpse
}

Expand Down
2 changes: 2 additions & 0 deletions src/mtype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ mon_flag_id mon_flag_ACIDPROOF,
mon_flag_PLASTIC,
mon_flag_POISON,
mon_flag_PRIORITIZE_TARGETS,
mon_flag_PULP_PRYING,
mon_flag_PUSH_MON,
mon_flag_PUSH_VEH,
mon_flag_QUEEN,
Expand Down Expand Up @@ -257,6 +258,7 @@ void set_mon_flag_ids()
mon_flag_PLASTIC = mon_flag_id( "PLASTIC" );
mon_flag_POISON = mon_flag_id( "POISON" );
mon_flag_PRIORITIZE_TARGETS = mon_flag_id( "PRIORITIZE_TARGETS" );
mon_flag_PULP_PRYING = mon_flag_id( "PULP_PRYING" );
mon_flag_PUSH_MON = mon_flag_id( "PUSH_MON" );
mon_flag_PUSH_VEH = mon_flag_id( "PUSH_VEH" );
mon_flag_QUEEN = mon_flag_id( "QUEEN" );
Expand Down
1 change: 1 addition & 0 deletions src/mtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ extern mon_flag_id mon_flag_ACIDPROOF,
mon_flag_PLASTIC,
mon_flag_POISON,
mon_flag_PRIORITIZE_TARGETS,
mon_flag_PULP_PRYING,
mon_flag_PUSH_MON,
mon_flag_PUSH_VEH,
mon_flag_QUEEN,
Expand Down
24 changes: 20 additions & 4 deletions src/npcmove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ static const itype_id itype_thorazine( "thorazine" );
static const npc_class_id NC_EVAC_SHOPKEEP( "NC_EVAC_SHOPKEEP" );

static const skill_id skill_firstaid( "firstaid" );
static const skill_id skill_swimming( "swimming" );

static const trait_id trait_IGNORE_SOUND( "IGNORE_SOUND" );
static const trait_id trait_RETURN_TO_START_POS( "RETURN_TO_START_POS" );
Expand Down Expand Up @@ -3917,10 +3918,25 @@ bool npc::find_corpse_to_pulp()
// Pulp only stuff that revives, but don't pulp acid stuff
// That is, if you aren't protected from this stuff!
if( it.can_revive() ) {
// If the first encountered corpse bleeds something dangerous then
// it is not safe to bash.
if( is_dangerous_field( field_entry( it.get_mtype()->bloodType(), 1, 0_turns ) ) ) {
return nullptr;

const mtype &corpse = *it.get_corpse_mon();
if( corpse.size > 3 ) {

// stripped copy of calculations from pulp_activity_actor::start()
std::pair<float, item> pair = get_best_weapon_by_damage_type( damage_bash );

const double weight_factor = units::to_kilogram( get_weight() ) / 10;
const double athletic_factor = std::min( 6.0f, get_skill_level( skill_swimming ) + 1 ) * 3;
const double strength_factor = get_str() / 2;
const float pulp_power_stomps = athletic_factor + weight_factor + strength_factor;
const double bash_factor = std::max( pulp_power_stomps, pair.first );

if( corpse.size == 4 && bash_factor < 33 ) {
continue;
}
if( corpse.size == 5 && bash_factor < 45 ) {
continue;
}
}

found = &it;
Expand Down
Loading