void FloorMapLayer::confirm_attack_impl(const npc_t& npc) { auto life = get_tile_prop(npc.gid, "life").asInt(); auto hun = get_tile_prop(npc.gid, "hun").asInt(); auto gold = get_tile_prop(npc.gid, "gold").asInt(); auto defence = get_tile_prop(npc.gid, "defence").asInt(); auto attack = get_tile_prop(npc.gid, "attack").asInt(); auto player_info = Player::GetInstance()->get_player_info(); auto attack_damage = std::max(0, player_info.attack - defence); auto damage = std::max(0, attack - player_info.defence); if (attack_damage == 0 || (life + attack_damage - 1) / attack_damage * damage >= player_info.hp) // 只要攻击不够无论防御多高都打不过 { auto dict = FileUtils::getInstance()->getValueMapFromFile("chinese.xml"); auto text = dict["txt7_2"].asString(); PromptDialog::show(text); stop_and_clear(); return; } auto blood = (life + attack_damage - 1) / attack_damage * damage; auto target_pos = this->convertToNodeSpace(_info_panel->get_node_position_in_world(WarriorInfoPanel::hun)); target_pos -= Vec2(26.0f, 0); pick_up_item_impl(npc, target_pos, [blood, gold, hun]() { PlayerDelegate::add_hp(-blood); PlayerDelegate::add_gold_hun(gold, hun); }); auto end_pos = Vec2((npc.x + 0.5f) * 75.0f - 50.0f, (npc.y + 0.5f) * 75.0f - 50.0f); _warrior->move_to(end_pos, CC_CALLBACK_0(FloorMapLayer::step, this)); _paths.erase(_paths.begin()); }
void FloorMapLayer::confirm_open(OKCancelDialog::RETURN_TYPE type, const npc_t& npc) { if (type == OKCancelDialog::CANCEL) { stop_and_clear(); } else { _warrior->stand_auto(); auto npc_layer = _tiled_map->getLayer("npc"); auto door = npc_layer->getTileAt(Vec2(npc.x, 11 - npc.y)); npc_layer->setupTileSprite(door, Vec2(npc.x, 11 - npc.y), npc.gid); door->runAction(CCSequence::create(FadeOut::create(0.5f), RemoveSelf::create(), CCCallFunc::create(std::bind(&FloorMapLayer::confirm_open_impl, this, npc)), nullptr)); // 如果是竖门需要将其上方的附加节点一并去除 auto uplink = get_tile_prop(npc.gid, "uplink").asInt(); if (1 == uplink) { auto npc_iter = find(_npcs.begin(), _npcs.end(), npc_t(npc.x, npc.y + 1, 0)); if (npc_iter != _npcs.end()) { const auto& npc_up = *npc_iter; auto door_up = npc_layer->getTileAt(Vec2(npc_up.x, 11 - npc_up.y)); npc_layer->setupTileSprite(door_up, Vec2(npc_up.x, 11 - npc_up.y), npc_up.gid); door_up->runAction(CCSequence::create(FadeOut::create(0.5f), RemoveSelf::create(), nullptr)); } } } }
void FloorMapLayer::confirm_open(OKCancelDialog::RETURN_TYPE type, const Floor::npc_t& npc) { if (type == OKCancelDialog::CANCEL) { stop_and_clear(); } else { _warrior->stand_auto(); _warrior->set_lock(true); // 设置等待开门的过程中不可重新寻路,以免出现计算混乱 auto npc_layer = _tiled_map->getLayer("npc"); auto door = npc_layer->getTileAt(Vec2(npc.pos.x, 11 - npc.pos.y)); npc_layer->setupTileSprite(door, Vec2(npc.pos.x, 11 - npc.pos.y), npc.gid); const float OPEN_DURATION = 0.5f; door->runAction(CCSequence::create(FadeOut::create(OPEN_DURATION), RemoveSelf::create(), CCCallFunc::create(std::bind(&FloorMapLayer::confirm_open_impl, this, npc)), nullptr)); // 如果是竖门需要将其上方的附加节点一并去除 auto uplink = get_tile_prop(npc.gid, "uplink").asInt(); if (1 == uplink) { auto npc_up = Floor::GetInstance()->get_floor_info(_floor).find_npc_by_pos(Floor::position_t(npc.pos.x, npc.pos.y + 1)); if (nullptr != npc_up) { auto door_up = npc_layer->getTileAt(Vec2(npc_up->pos.x, 11 - npc_up->pos.y)); npc_layer->setupTileSprite(door_up, Vec2(npc_up->pos.x, 11 - npc_up->pos.y), npc_up->gid); door_up->runAction(CCSequence::create(FadeOut::create(OPEN_DURATION), RemoveSelf::create(), nullptr)); } } } }
void FloorMapLayer::step() { if (_paths.empty()) { return; } auto current_pos = _warrior->getPosition(); auto start_pt = _paths[0]; auto start_pos = Vec2((start_pt.x + 0.5f) * 75.0f - 50.0f, (start_pt.y + 0.5f) * 75.0f - 50.0f); // 勇士位置在开始位置正中心时触发拾取操作,如果还没到,代表未到触发时机,如果已走过,代表触发前取消当前操作并改变路径 if (current_pos.equals(start_pos)) { auto npc = Floor::GetInstance()->get_floor_info(_floor).find_npc_by_pos(start_pt); if (nullptr != npc) pick_up_item(*npc); } // 未走到路径末尾,继续处理下一步行走 if (_paths.size() > 1) { auto end_pt = _paths[1]; auto end_pos = Vec2((end_pt.x + 0.5f) * 75.0f - 50.0f, (end_pt.y + 0.5f) * 75.0f - 50.0f); // 如果需要额外走一段到瓦块中心,仅仅执行这段走路,仅在走到块间时重新改变行走路径时有效 if (current_pos.distance(end_pos) > start_pos.distance(end_pos)) { _warrior->move_to(start_pos, CC_CALLBACK_0(FloorMapLayer::step, this)); return; } // 淡出脚下的路径标识 auto road_children = _road_node->getChildren(); auto child = dynamic_cast<Node*>(road_children.at(road_children.size() + 1 - _paths.size())); if (nullptr != child) { child->runAction(FadeOut::create(0.2f)); } bool walk_pause = false; auto npc = Floor::GetInstance()->get_floor_info(_floor).find_npc_by_pos(end_pt); if (nullptr != npc) walk_pause = interact_item(*npc); if (!walk_pause) { _warrior->move_to(end_pos, CC_CALLBACK_0(FloorMapLayer::step, this)); _paths.erase(_paths.begin()); } } else // 走到寻路最后一个节点,清理工作 { stop_and_clear(); } }
void FloorMapLayer::confirm_attack(OKCancelDialog::RETURN_TYPE type, const npc_t& npc) { if (type == OKCancelDialog::CANCEL) { stop_and_clear(); } else { static int attack_count = 3; attack_count = 3; _warrior->fight_auto(3, std::bind(&FloorMapLayer::confirm_attack_impl, this, npc)); } }
bool FloorMapLayer::interact_item(const npc_t& npc) { bool walk_pause = false; auto style = get_tile_prop(npc.gid, "style").asInt(); switch (style) { case 1: // 怪物 { walk_pause = true; auto end_pos = Vec2((npc.x + 0.5f) * 75.0f - 50.0f, (npc.y + 0.5f) * 75.0f - 50.0f); _warrior->turn_to(end_pos); if (_paths.size() > 2) // 怪物为行走路径的最后一个节点,不提示对话框,直接开打 { auto dict = FileUtils::getInstance()->getValueMapFromFile("chinese.xml"); auto text = dict["isAttack"].asString(); auto name = dict[get_tile_prop(npc.gid, "name").asString()].asString(); auto info = text + " " + name; auto dialog = OKCancelDialog::create("", info); dialog->setCallback(std::bind(&FloorMapLayer::confirm_attack, this, std::placeholders::_1, npc)); ModalDialogManager::GetInstance()->pushDialog(dialog); } else { assert(_paths.size() == 2); // 和npc交互时路径肯定还有至少两个节点,一个自己的,一个对方的 if (_paths.size() == 2) confirm_attack(OKCancelDialog::OK, npc); } } break; case 3: // 门 { walk_pause = true; auto end_pos = Vec2((npc.x + 0.5f) * 75.0f - 50.0f, (npc.y + 0.5f) * 75.0f - 50.0f); _warrior->turn_to(end_pos); auto color = get_tile_prop(npc.gid, "color").asInt(); const auto& player = Player::GetInstance()->get_player_info(); if (1 == color && player.key_red < 1 || 2 == color && player.key_blue < 1 || 3 == color && player.key_yellow < 1) { auto dict = FileUtils::getInstance()->getValueMapFromFile("chinese.xml"); auto text = dict["buyKeyTip"].asString(); PromptDialog::show(text); stop_and_clear(); break; } auto dict = FileUtils::getInstance()->getValueMapFromFile("chinese.xml"); auto prefix = dict["open_msg1"].asString(); auto sufix = dict["open_msg2"].asString(); auto textkey = 1 == color ? "rKey" : (2 == color ? "bKey" : "yKey"); auto info = prefix + dict[textkey].asString() + sufix; auto dialog = OKCancelDialog::create("", info); dialog->setCallback(std::bind(&FloorMapLayer::confirm_open, this, std::placeholders::_1, npc)); ModalDialogManager::GetInstance()->pushDialog(dialog); } break; case 6: // 楼梯 { walk_pause = false; // 无需停下来,直接切换楼层,切换场景的持续时间的一半让勇士正好走入下一个楼梯格子 auto next_scene = PromptLayer::scene(_floor == 1 ? 2 : 1); auto transition = TransitionFade::create(0.5f, next_scene); Director::getInstance()->replaceScene(transition); } break; default: break; } return walk_pause; }