bool place_free(dungeon_t* dungeon, int x, int y, creature_t* creature) { int index = y * dungeon->width + x; tile_t* tile = &dungeon->map[index]; if (creature) { if (!tile_is_walkable_by(*tile, creature)) return false; } else { if (!(tile->properties & TILE_PROP_WALKABLE)) return false; } if (get_creature_at(dungeon, x, y)) return false; if (player.pos.x == x && player.pos.y == y) return false; if (count_items_at(dungeon, x, y) > 0) return false; return true; }
bool autochat() { std::vector<creature_t*> found_creatures; for (int y = player.pos.y - 1; y <= player.pos.y + 1; y++) { for (int x = player.pos.x - 1; x <= player.pos.x + 1; x++) { creature_t* creature = get_creature_at(current_dungeon, x, y); if (creature) { found_creatures.push_back(creature); } } } if (found_creatures.size() == 1) { chat(found_creatures.front()); return true; } return false; }
coord_t pick_walkable_position_in_area(dungeon_t* dungeon, int start_x, int start_y, int end_x, int end_y, creature_t* creature) { std::vector<coord_t> coords; for (int y = start_y; y < end_y; y++) { for (int x = start_x; x < end_x; x++) { if (x >= 0 && y >= 0 && x < dungeon->width && y < dungeon->height && get_creature_at(dungeon, x, y) == 0) { tile_t* tile = get_tile_at(dungeon, x, y); if (creature && tile_is_walkable_by(*tile, creature)) { coord_t coord = {x, y}; coords.push_back(coord); } } } } if (coords.size() > 0) { std::random_shuffle(coords.begin(), coords.end()); return coords.front(); } coord_t bad = {-1, -1}; return bad; }
bool CCreature::trymove( int relative_x, int relative_y ) { if(main_map.get_grid_at(x + relative_x,y + relative_y) == WALL_CHAR) return false; if (get_creature_at(x + relative_x, y + relative_y)) return false; unmap(); x += relative_x; y += relative_y; map(); return true; }
int _is_ally_in_ray(creature_t* caster, creature_t* target) { int x, y; TCODLine::init(caster->pos.x, caster->pos.y, target->pos.x, target->pos.y); while (!TCODLine::step(&x, &y)) { creature_t* creature = get_creature_at(current_dungeon, x, y); if (creature && creature_t::is_allies(caster, creature)) return 1; } return 0; }
bool CCreature::tryattack( int relative_x, int relative_y ) { if (! (relative_x != 0) ^ (relative_y != 0)) return false; if(abs(relative_x) > 1 || abs(relative_y) > 1) return false; CCreature * creat = get_creature_at(x + relative_x, y + relative_y); if (!creat) return false; //disp.gameprintf("%s attacks %s.", get_name(), creat->get_name()); creat->takedamage(get_attack_dmg(), get_AP()); return true; }
coord_t _get_random_walkable_for_item(dungeon_t* dungeon) { int px, py; do { px = random(0, dungeon->width - 1); py = random(0, dungeon->height - 1); } while (!(get_tile_at(dungeon, px, py)->properties & TILE_PROP_WALKABLE) || get_creature_at(dungeon, px, py)); coord_t coord = { px, py }; return coord; }
void creature_t::try_move(int move_x, int move_y) { tile_t* tile = get_tile_at(current_dungeon, move_x, move_y); if (tile && (tile_is_walkable_by(*tile, this))) { creature_t* thing = get_creature_at(current_dungeon, move_x, move_y); if (thing) { if (get_active_effects_for(this) & EF_CONFUSE) { creature_attacks(this, thing); } else if ((is_ally() && !thing->is_ally()) || (!is_ally() && thing->is_ally())) { // The two creatures are enemies. creature_attacks(this, thing); } } else if (player.pos.x == move_x && player.pos.y == move_y) { if (!is_friendly() || (get_active_effects_for(this) & EF_CONFUSE)) { // Not ally with player, or confused. creature_attacks(this, &player); } } else { pos.x = move_x; pos.y = move_y; } } else if (tile && tile->id == TILE_DOOR_CLOSED) { if (flag & CF_INTELLIGENT) { open_door(current_dungeon, this, move_x, move_y); //creature->pos.x = move_x; //creature->pos.y = move_y; } } }
void _take_stairs(stairs_t* stairs) { dungeon_t* prev_dungeon = current_dungeon; TRACE("take_stairs: stairs->to_branch=%s", stairs->to_branch.c_str()); // Arrive from town to infinite dungeon: clear infinite dungeon. if (stairs->to && stairs->to_branch == BRANCH_INFINITE_DUNGEON && current_branch->name != BRANCH_INFINITE_DUNGEON) { stairs->to = nullptr; branch_t* inf_branch = find_branch(stairs->to_branch); for (dungeon_t* dungeon : inf_branch->dungeons) { destroy_dungeon(dungeon); } inf_branch->dungeons.clear(); } // Generate the next dungeon if needed. if (stairs->to == nullptr && stairs->to_branch == current_branch->name) { dungeon_t* next_level = generate_next_level(current_branch); create_up_stairs(next_level, current_branch, prev_dungeon, stairs); } else if (stairs->to == nullptr) { // Stairs to a new branch. branch_t* prev_branch = current_branch; current_branch = create_branch(stairs->to_branch); dungeon_t* next_level = current_branch->dungeons.front(); // Check if the level has stairs that lead back to the branch already. bool has_stairs = false; for (int i = 0; i < next_level->num_stairs; i++) { if (next_level->stairs[i]->to_branch == prev_branch->name) has_stairs = true; } if (!has_stairs) create_up_stairs(next_level, prev_branch, prev_dungeon, stairs); else stairs->to = next_level; } dungeon_t* dst = stairs->to; current_dungeon = dst; current_branch = find_branch(stairs->to_branch); player.pos.x = stairs->warp_x; player.pos.y = stairs->warp_y; // Do not follow player to the world map. if (current_branch->name != "World") { std::vector<coord_t> free_coords; for (int y = player.pos.y - 1; y <= player.pos.y + 1; y++) for (int x = player.pos.x - 1; x <= player.pos.x + 1; x++) if (place_free(current_dungeon, x, y)) free_coords.push_back( coord_t { x, y} ); std::vector<creature_t*> following_creatures; for (int y = stairs->y - 1; y <= stairs->y + 1; y++) { for (int x = stairs->x - 1; x <= stairs->x + 1; x++) { creature_t* creature = get_creature_at(prev_dungeon, x, y); if (creature && following_creatures.size() < free_coords.size()) { following_creatures.push_back(creature); remove_creature_no_destroy(prev_dungeon, creature); } } } for (size_t i = 0; i < following_creatures.size(); i++) { add_creature_to_dungeon(current_dungeon, following_creatures[i], free_coords[i].x, free_coords[i].y); } if (following_creatures.size() == 1) append_msg_log("%s follows you.", capitalize(following_creatures.front()->get_full_name()).c_str()); else if (following_creatures.size() > 1) append_msg_log("Some creatures follow you."); } clear_action_list(); append_action_list(&player); }
void _select_direction() { const std::string move_keys = "lkjhyubn12346789"; int state = statestack_top(); char key = io::getchar(); if (char_in(key, move_keys)) { if (state == STATE_CLOSE_DOOR) { int x, y; x = player.pos.x; y = player.pos.y; compute_xy_by_direction(direction_from_key(key), &x, &y); tile_t* tile = get_tile_at(current_dungeon, x, y); if (tile->id == TILE_DOOR_OPEN) { if (place_free(current_dungeon, x, y) && count_items_at(current_dungeon, x, y) == 0) { close_door(current_dungeon, &player, x, y); player.ap -= player.speed; } else { append_msg_log("The door is blocked!"); } } else if (tile->id == TILE_DOOR_CLOSED) { append_msg_log("That door is already closed."); } else { append_msg_log("There is no door there!"); } statestack_pop(); } else if (state == STATE_CHAT) { int x = player.pos.x; int y = player.pos.y; compute_xy_by_direction(direction_from_key(key), &x, &y); creature_t* creature = get_creature_at(current_dungeon, x, y); if (creature) { chat(creature); } else { append_msg_log("There is no one there to talk to!"); } statestack_pop(); } return; } if (key == '\x1B') { append_msg_log("Nevermind."); statestack_pop(); } }
void _move_targeting_cursor() { coord_t old_target = target_cursor_position(); const std::string move_keys = "lkjhyubn12346789vg"; int state = statestack_top(); char key = io::getchar(); if (key == 'v' && state == STATE_EXAMINE) { coord_t pos = target_cursor_position(); creature_t* creature_at_tile = get_creature_at(current_dungeon, pos.x, pos.y); if (creature_at_tile) { describe(creature_at_tile); } // Print tile info after so it doesn't dissapear. _examine_tile(pos.x, pos.y); } else if (key == 'g' && state == STATE_EXAMINE) { coord_t pos = target_cursor_position(); if (position_in_fov(current_dungeon, pos.x, pos.y)) { statestack_pop(); _start_travel(0, true, pos.x, pos.y); } else { append_msg_log("You can't travel where you can't see!"); } } else if (char_in(key, "<>") && state == STATE_EXAMINE) { for (int y = 0; y < current_dungeon->height; y++) { for (int x = 0; x < current_dungeon->width; x++) { const tile_t* tile = get_tile_at(current_dungeon, x, y); TileType tile_type = key == '<' ? TILE_STAIRS_UP : TILE_STAIRS_DOWN; if (tile->id == tile_type && position_in_fov(current_dungeon, x, y)) { init_target_cursor(x, y, false); } } } } else if (char_in(key, move_keys)) { move_target_cursor(direction_from_key(key)); if (state == STATE_EXAMINE) { coord_t target_coord = target_cursor_position(); _examine_tile(target_coord.x, target_coord.y); } else if (state == STATE_ZAP_WAND) { coord_t target_coord = target_cursor_position(); const spell_t* wand_spell = get_spell_for_wand(get_current_wand()); if (wand_spell) { if (!in_range_of_spell(wand_spell, &player, target_coord.x, target_coord.y)) { init_target_cursor(old_target.x, old_target.y, true); } } } else if (state == STATE_CAST_SPELL) { coord_t target_coord = target_cursor_position(); if (!in_range_of_spell(current_spell, &player, target_coord.x, target_coord.y)) { init_target_cursor(old_target.x, old_target.y, spell_is_ray_or_missile(current_spell)); } } return; } if (key == '\x1B') { statestack_pop(); } else if (key == ' ' || key == '\n') { // What this does depends on state. if (state == STATE_EXAMINE) { statestack_pop(); } else if (state == STATE_ZAP_WAND) { const spell_t* wand_spell = get_spell_for_wand(get_current_wand()); coord_t target_coord = target_cursor_position(); if (wand_spell && in_range_of_spell(wand_spell, &player, target_coord.x, target_coord.y)) { if (fov_value_at(current_dungeon, target_coord.x, target_coord.y) == LIT) { fire_wand(get_current_wand(), &player, target_coord); statestack_pop(); } else { append_msg_log("You can't fire your wand where you cannot see."); } } else { append_msg_log("Out of range."); } } else if (state == STATE_CAST_SPELL) { coord_t target_coord = target_cursor_position(); if (in_range_of_spell(current_spell, &player, target_coord.x, target_coord.y)) { if (fov_value_at(current_dungeon, target_coord.x, target_coord.y) == LIT) { cast_spell(current_spell, &player, target_coord.x, target_coord.y); statestack_pop(); } else { append_msg_log("You can't cast a spell where you cannot see."); } } else { append_msg_log("Out of range."); } } } }