void game::draw_hit_player(player const &p, const int dam) { if (!use_tiles) { draw_hit_player_curses(*this, p, dam); return; } static std::string const player_male { "player_male" }; static std::string const player_female { "player_female" }; static std::string const npc_male { "npc_male" }; static std::string const npc_female { "npc_female" }; std::string const& type = p.is_player() ? (p.male ? player_male : player_female) : (p.male ? npc_male : npc_female); tilecontext->init_draw_hit( p.pos3(), type ); wrefresh(w_terrain); draw_animation_delay(); }
void game::draw_hit_mon( const tripoint &p, const monster &m, bool const dead ) { if (!use_tiles) { draw_hit_mon_curses( p, m, u, dead ); return; } tilecontext->init_draw_hit( p, m.type->id.str() ); wrefresh(w_terrain); draw_animation_delay(); }
void game::draw_explosion( const tripoint &p, int const r, nc_color const col ) { if (!use_tiles) { draw_explosion_curses(*this, p, r, col); return; } for (int i = 1; i <= r; i++) { tilecontext->init_explosion( p, i ); // TODO not xpos ypos? wrefresh(w_terrain); draw_animation_delay(EXPLOSION_MULTIPLIER); } if (r > 0) { tilecontext->void_explosion(); } }
// need to have a version where there is no player defined, possibly. That way shrapnel works as intended void game::draw_bullet(Creature const &p, const tripoint &t, int const i, std::vector<tripoint> const &trajectory, char const bullet) { //TODO signature and impl could be changed to eliminate these params (void)i; //unused (void)trajectory; //unused if( !u.sees( t ) ) { return; } if (!use_tiles) { draw_bullet_curses(w_terrain, u, m, t, bullet, nullptr, p.is_player()); return; } static std::string const bullet_unknown {}; static std::string const bullet_normal { "animation_bullet_normal" }; static std::string const bullet_flame { "animation_bullet_flame" }; static std::string const bullet_shrapnel { "animation_bullet_shrapnel" }; std::string const &bullet_type = (bullet == '*') ? bullet_normal : (bullet == '#') ? bullet_flame : (bullet == '`') ? bullet_shrapnel : bullet_unknown; tilecontext->init_draw_bullet( t, bullet_type ); wrefresh(w_terrain); if( p.is_player() ) { draw_animation_delay(); } tilecontext->void_bullet(); }
void game::draw_custom_explosion( const tripoint &, const std::map<tripoint, nc_color> &all_area ) { constexpr explosion_neighbors all_neighbors = N_NORTH | N_SOUTH | N_WEST | N_EAST; // We will "shell" the explosion area // Each phase will strip a single layer of points // A layer contains all points that have less than 4 neighbors in cardinal directions // Layers will first be generated, then drawn in inverse order // Start by getting rid of everything except current z-level std::map<point, explosion_tile> neighbors; #if defined(TILES) if( !use_tiles ) { for( const auto &pr : all_area ) { const tripoint relative_point = relative_view_pos( u, pr.first ); if( relative_point.z == 0 ) { point flat_point{ relative_point.x, relative_point.y }; neighbors[flat_point] = explosion_tile{ N_NO_NEIGHBORS, pr.second }; } } } else { // In tiles mode, the coordinates have to be absolute const tripoint view_center = relative_view_pos( u, u.pos() ); for( const auto &pr : all_area ) { const tripoint &pt = pr.first; // Relative point is only used for z level check const tripoint relative_point = relative_view_pos( u, pr.first ); if( relative_point.z == view_center.z ) { point flat_point{ pt.x, pt.y }; neighbors[flat_point] = explosion_tile{ N_NO_NEIGHBORS, pr.second }; } } } #else for( const auto &pr : all_area ) { const tripoint relative_point = relative_view_pos( u, pr.first ); if( relative_point.z == 0 ) { point flat_point{ relative_point.x, relative_point.y }; neighbors[flat_point] = explosion_tile{ N_NO_NEIGHBORS, pr.second }; } } #endif // Searches for a neighbor, sets the neighborhood flag on current point and on the neighbor const auto set_neighbors = [&]( const point &pos, explosion_neighbors &ngh, explosion_neighbors here, explosion_neighbors there ) { if( ( ngh & here ) == N_NO_NEIGHBORS ) { auto other = neighbors.find( pos ); if( other != neighbors.end() ) { ngh = ngh | here; other->second.neighborhood = other->second.neighborhood | there; } } }; // If the point we are about to remove has a neighbor in a given direction // unset that neighbor's flag that our current point is its neighbor const auto unset_neighbor = [&]( const point &pos, const explosion_neighbors ngh, explosion_neighbors here, explosion_neighbors there ) { if( ( ngh & here ) != N_NO_NEIGHBORS ) { auto other = neighbors.find( pos ); if( other != neighbors.end() ) { other->second.neighborhood = ( other->second.neighborhood | there ) ^ there; } } }; // Find all neighborhoods for( auto &pr : neighbors ) { const point &pt = pr.first; explosion_neighbors &ngh = pr.second.neighborhood; set_neighbors( point( pt.x - 1, pt.y ), ngh, N_WEST, N_EAST ); set_neighbors( point( pt.x + 1, pt.y ), ngh, N_EAST, N_WEST ); set_neighbors( point( pt.x, pt.y - 1 ), ngh, N_NORTH, N_SOUTH ); set_neighbors( point( pt.x, pt.y + 1 ), ngh, N_SOUTH, N_NORTH ); } // We need to save the layers because we will draw them in reverse order std::list< std::map<point, explosion_tile> > layers; bool changed; while( !neighbors.empty() ) { std::map<point, explosion_tile> layer; changed = false; // Find a layer that can be drawn for( const auto &pr : neighbors ) { if( pr.second.neighborhood != all_neighbors ) { changed = true; layer.insert( pr ); } } if( !changed ) { // An error, but a minor one - let it slide return; } // Remove the layer from the area to process for( const auto &pr : layer ) { const point &pt = pr.first; const explosion_neighbors ngh = pr.second.neighborhood; unset_neighbor( point( pt.x - 1, pt.y ), ngh, N_WEST, N_EAST ); unset_neighbor( point( pt.x + 1, pt.y ), ngh, N_EAST, N_WEST ); unset_neighbor( point( pt.x, pt.y - 1 ), ngh, N_NORTH, N_SOUTH ); unset_neighbor( point( pt.x, pt.y + 1 ), ngh, N_SOUTH, N_NORTH ); neighbors.erase( pr.first ); } layers.push_front( std::move( layer ) ); } #if defined(TILES) if( !use_tiles ) { draw_custom_explosion_curses( *this, layers ); return; } // We need to draw all explosions up to now std::map<point, explosion_tile> combined_layer; for( const auto &layer : layers ) { combined_layer.insert( layer.begin(), layer.end() ); tilecontext->init_custom_explosion_layer( combined_layer ); wrefresh(w_terrain); draw_animation_delay(EXPLOSION_MULTIPLIER); } tilecontext->void_custom_explosion(); #else draw_custom_explosion_curses( *this, layers ); #endif }