void Player::moveAction(Vec2 dir) { if (auto action = creature->move(dir)) { action.perform(); itemsMessage(); } else if (const Creature *c = creature->getConstSquare(dir)->getCreature()) { if (auto action = creature->bumpInto(dir)) action.perform(); else if (auto action = creature->destroy(dir, Creature::BASH)) action.perform(); } }
void Player::targetAction() { CHECK(target); if (creature->getPosition() == *target || model->getView()->travelInterrupt()) { target = Nothing(); return; } if (auto action = creature->moveTowards(*target)) action.perform(); else target = Nothing(); itemsMessage(); if (interruptedByEnemy()) target = Nothing(); }
void Player::targetAction() { CHECK(target); if (creature->getPosition() == *target || model->getView()->travelInterrupt()) { target = Nothing(); return; } Optional<Vec2> move = creature->getMoveTowards(*target); if (move) creature->move(*move); else target = Nothing(); itemsMessage(); if (interruptedByEnemy()) target = Nothing(); }
void Player::travelAction() { if (!creature->canMove(travelDir) || model->getView()->travelInterrupt() || interruptedByEnemy()) { travelling = false; return; } creature->move(travelDir); itemsMessage(); const Location* currentLocation = creature->getLevel()->getLocation(creature->getPosition()); if (lastLocation != currentLocation && currentLocation != nullptr && currentLocation->hasName()) { privateMessage("You arrive at " + addAParticle(currentLocation->getName())); travelling = false; return; } vector<Vec2> squareDirs = creature->getConstSquare()->getTravelDir(); if (squareDirs.size() != 2) { travelling = false; Debug() << "Stopped by multiple routes"; return; } Optional<int> myIndex = findElement(squareDirs, -travelDir); CHECK(myIndex) << "Bad travel data in square"; travelDir = squareDirs[(*myIndex + 1) % 2]; }
void Player::makeMove() { vector<Vec2> squareDirs = creature->getConstSquare()->getTravelDir(); const vector<Creature*>& creatures = creature->getLevel()->getAllCreatures(); if (creature->isAffected(Creature::HALLU)) ViewObject::setHallu(true); else ViewObject::setHallu(false); MEASURE( model->getView()->refreshView(creature), "level render time"); if (Options::getValue(OptionId::HINTS) && displayTravelInfo && creature->getConstSquare()->getName() == "road") { model->getView()->presentText("", "Use ctrl + arrows to travel quickly on roads and corridors."); displayTravelInfo = false; } static bool greeting = false; if (Options::getValue(OptionId::HINTS) && displayGreeting) { CHECK(creature->getFirstName()); model->getView()->presentText("", "Dear " + *creature->getFirstName() + ",\n \n \tIf you are reading this letter, then you have arrived in the valley of " + NameGenerator::worldNames.getNext() + ". There is a band of dwarves dwelling in caves under a mountain. Find them, talk to them, they will help you. Let your sword guide you.\n \n \nYours, " + NameGenerator::firstNames.getNext() + "\n \nPS.: Beware the goblins!"); model->getView()->presentText("", "Every settlement that you find has a leader, and they may have quests for you." "\n \nYou can turn these messages off in the options (press F2)."); displayGreeting = false; model->getView()->refreshView(creature); } for (const Creature* c : creature->getVisibleEnemies()) { if (c->isSpecialMonster() && !contains(specialCreatures, c)) { privateMessage(MessageBuffer::important(c->getDescription())); model->getView()->refreshView(creature); specialCreatures.push_back(c); } } if (travelling) travelAction(); else if (target) targetAction(); else { Action action = model->getView()->getAction(); vector<Vec2> direction; bool travel = false; switch (action.getId()) { case ActionId::FIRE: fireAction(action.getDirection()); break; case ActionId::TRAVEL: travel = true; case ActionId::MOVE: direction.push_back(action.getDirection()); break; case ActionId::MOVE_TO: if (action.getDirection().dist8(creature->getPosition()) == 1) { Vec2 dir = action.getDirection() - creature->getPosition(); if (const Creature* c = creature->getConstSquare(dir)->getCreature()) { if (!creature->isEnemy(c)) { chatAction(dir); break; } } direction.push_back(dir); } else if (action.getDirection() != creature->getPosition()) { target = action.getDirection(); target = Vec2(min(creature->getLevel()->getBounds().getKX() - 1, max(0, target->x)), min(creature->getLevel()->getBounds().getKY() - 1, max(0, target->y))); // Just in case if (!target->inRectangle(creature->getLevel()->getBounds())) target = Nothing(); } else pickUpAction(false); break; case ActionId::SHOW_INVENTORY: displayInventory(); break; case ActionId::PICK_UP: pickUpAction(false); break; case ActionId::EXT_PICK_UP: pickUpAction(true); break; case ActionId::DROP: dropAction(false); break; case ActionId::EXT_DROP: dropAction(true); break; case ActionId::WAIT: creature->wait(); break; case ActionId::APPLY_ITEM: applyAction(); break; case ActionId::THROW: throwAction(); break; case ActionId::THROW_DIR: throwAction(action.getDirection()); break; case ActionId::EQUIPMENT: equipmentAction(); break; case ActionId::HIDE: hideAction(); break; case ActionId::PAY_DEBT: payDebtAction(); break; case ActionId::CHAT: chatAction(); break; case ActionId::SHOW_HISTORY: messageBuffer.showHistory(); break; case ActionId::UNPOSSESS: if (creature->canPopController()) { creature->popController(); return; } break; case ActionId::CAST_SPELL: spellAction(); break; case ActionId::DRAW_LEVEL_MAP: model->getView()->drawLevelMap(creature); break; case ActionId::EXIT: model->exitAction(); break; case ActionId::IDLE: break; } if (creature->isAffected(Creature::SLEEP) && creature->canPopController()) { if (model->getView()->yesOrNoPrompt("You fell asleep. Do you want to leave your minion?")) creature->popController(); return; } for (Vec2 dir : direction) if (travel) { vector<Vec2> squareDirs = creature->getConstSquare()->getTravelDir(); if (findElement(squareDirs, dir)) { travelDir = dir; lastLocation = creature->getLevel()->getLocation(creature->getPosition()); travelling = true; travelAction(); } } else if (creature->canMove(dir)) { creature->move(dir); itemsMessage(); break; } else { const Creature *c = creature->getConstSquare(dir)->getCreature(); if (creature->canBumpInto(dir)) { creature->bumpInto(dir); break; } else if (creature->canDestroy(dir)) { privateMessage("You bash the " + creature->getSquare(dir)->getName()); creature->destroy(dir); break; } } } for (Vec2 pos : creature->getLevel()->getVisibleTiles(creature)) { ViewIndex index = creature->getLevel()->getSquare(pos)->getViewIndex(creature); (*levelMemory)[creature->getLevel()].clearSquare(pos); for (ViewLayer l : { ViewLayer::ITEM, ViewLayer::FLOOR_BACKGROUND, ViewLayer::FLOOR, ViewLayer::LARGE_ITEM}) if (index.hasObject(l)) remember(pos, index.getObject(l)); } }