void draw_opener_floor_fg (ALLEGRO_BITMAP *bitmap, struct pos *p, enum em em, enum vm vm) { if (is_fake (p)) return; struct opener_floor *o = opener_floor_at_pos (p); if (! o) return; if (o->broken) { draw_broken_floor_fg (bitmap, p, em, vm); return; } }
void draw_opener_floor_right (ALLEGRO_BITMAP *bitmap, struct pos *p, enum em em, enum vm vm) { if (is_fake (p)) { draw_unpressed_opener_floor_right (bitmap, p, em, vm); return; } struct opener_floor *o = opener_floor_at_pos (p); if (! o) return; if (o->broken) { draw_broken_floor_right (bitmap, p, em, vm); return; } if (o->pressed) draw_floor_right (bitmap, p, em, vm); else draw_unpressed_opener_floor_right (bitmap, p, em, vm); }
Creature *Creature::auto_find_hostile_target( int range, int &boo_hoo, int area ) { Creature *target = nullptr; player &u = g->u; // Could easily protect something that isn't the player constexpr int hostile_adj = 2; // Priority bonus for hostile targets const int iff_dist = ( range + area ) * 3 / 2 + 6; // iff check triggers at this distance int iff_hangle = 15 + area; // iff safety margin (degrees). less accuracy, more paranoia float best_target_rating = -1.0f; // bigger is better int u_angle = 0; // player angle relative to turret boo_hoo = 0; // how many targets were passed due to IFF. Tragically. bool self_area_iff = false; // Need to check if the target is near the vehicle we're a part of bool area_iff = false; // Need to check distance from target to player bool angle_iff = true; // Need to check if player is in a cone between us and target int pldist = rl_dist( pos(), g->u.pos() ); vehicle *in_veh = is_fake() ? veh_pointer_or_null( g->m.veh_at( pos() ) ) : nullptr; if( pldist < iff_dist && sees( g->u ) ) { area_iff = area > 0; angle_iff = true; // Player inside vehicle won't be hit by shots from the roof, // so we can fire "through" them just fine. const optional_vpart_position vp = g->m.veh_at( u.pos() ); if( in_veh && veh_pointer_or_null( vp ) == in_veh && vp->is_inside() ) { angle_iff = false; // No angle IFF, but possibly area IFF } else if( pldist < 3 ) { iff_hangle = (pldist == 2 ? 30 : 60); // granularity increases with proximity } u_angle = g->m.coord_to_angle(posx(), posy(), u.posx(), u.posy()); } if( area > 0 && in_veh != nullptr ) { self_area_iff = true; } std::vector<Creature*> targets = g->get_creatures_if( [&]( const Creature &critter ) { if( const monster *const mon_ptr = dynamic_cast<const monster*>( &critter ) ) { // friendly to the player, not a target for us return mon_ptr->friendly == 0; } if( const npc *const npc_ptr = dynamic_cast<const npc*>( &critter ) ) { // friendly to the player, not a target for us return npc_ptr->get_attitude() == NPCATT_KILL; } //@todo: what about g->u? return false; } ); for( auto &m : targets ) { if( !sees( *m ) ) { // can't see nor sense it continue; } int dist = rl_dist( pos(), m->pos() ) + 1; // rl_dist can be 0 if( dist > range + 1 || dist < area ) { // Too near or too far continue; } // Prioritize big, armed and hostile stuff float mon_rating = m->power_rating(); float target_rating = mon_rating / dist; if( mon_rating + hostile_adj <= 0 ) { // We wouldn't attack it even if it was hostile continue; } if( in_veh != nullptr && veh_pointer_or_null( g->m.veh_at( m->pos() ) ) == in_veh ) { // No shooting stuff on vehicle we're a part of continue; } if( area_iff && rl_dist( u.pos(), m->pos() ) <= area ) { // Player in AoE boo_hoo++; continue; } // Hostility check can be expensive, but we need to inform the player of boo_hoo // only when the target is actually "hostile enough" bool maybe_boo = false; if( angle_iff ) { int tangle = g->m.coord_to_angle(posx(), posy(), m->posx(), m->posy()); int diff = abs(u_angle - tangle); // Player is in the angle and not too far behind the target if( ( diff + iff_hangle > 360 || diff < iff_hangle ) && ( dist * 3 / 2 + 6 > pldist ) ) { maybe_boo = true; } } if( !maybe_boo && ( ( mon_rating + hostile_adj ) / dist <= best_target_rating ) ) { // "Would we skip the target even if it was hostile?" // Helps avoid (possibly expensive) attitude calculation continue; } if( m->attitude_to( u ) == A_HOSTILE ) { target_rating = ( mon_rating + hostile_adj ) / dist; if( maybe_boo ) { boo_hoo++; continue; } } if( target_rating <= best_target_rating || target_rating <= 0 ) { continue; // Handle this late so that boo_hoo++ can happen } // Expensive check for proximity to vehicle if( self_area_iff && overlaps_vehicle( in_veh->get_points(), m->pos(), area ) ) { continue; } target = m; best_target_rating = target_rating; } return target; }