void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const { InfoWindow iw; iw.player = h->getOwner(); if (quest->progress < CQuest::COMPLETE) { bool firstVisit = !quest->progress; bool failRequirements = !checkQuest(h); bool isCustom=false; if (firstVisit) { isCustom = quest->isCustomFirst; cb->setObjProperty (id, 10, CQuest::IN_PROGRESS); AddQuest aq; aq.quest = QuestInfo (quest, this, visitablePos()); aq.player = h->tempOwner; cb->sendAndApply (&aq); //TODO: merge with setObjProperty? } else if (failRequirements) { isCustom = quest->isCustomNext; } if (firstVisit || failRequirements) { getVisitText (iw.text, iw.components, isCustom, firstVisit, h); cb->showInfoDialog(&iw); } if (!failRequirements) // propose completion, also on first visit { BlockingDialog bd (true, false); bd.player = h->getOwner(); bd.soundID = soundBase::QUEST; getCompletionText (bd.text, bd.components, isCustom, h); cb->showBlockingDialog (&bd); return; } } else { iw.text << VLC->generaltexth->seerEmpty[quest->textOption]; if (ID == Obj::SEER_HUT) iw.text.addReplacement(seerName); cb->showInfoDialog(&iw); } }
void CQuest::getVisitText (MetaString &iwText, std::vector<Component> &components, bool isCustom, bool firstVisit, const CGHeroInstance * h) const { std::string text; bool failRequirements = (h ? !checkQuest(h) : true); if (firstVisit) { isCustom = isCustomFirst; iwText << (text = firstVisitText); } else if (failRequirements) { isCustom = isCustomNext; iwText << (text = nextVisitText); } switch (missionType) { case MISSION_LEVEL: components.push_back(Component (Component::EXPERIENCE, 0, m13489val, 0)); if (!isCustom) iwText.addReplacement(m13489val); break; case MISSION_PRIMARY_STAT: { MetaString loot; for (int i = 0; i < 4; ++i) { if (m2stats[i]) { components.push_back(Component (Component::PRIM_SKILL, i, m2stats[i], 0)); loot << "%d %s"; loot.addReplacement(m2stats[i]); loot.addReplacement(VLC->generaltexth->primarySkillNames[i]); } } if (!isCustom) iwText.addReplacement(loot.buildList()); } break; case MISSION_KILL_HERO: components.push_back(Component(Component::HERO_PORTRAIT, heroPortrait, 0, 0)); if (!isCustom) addReplacements(iwText, text); break; case MISSION_HERO: //FIXME: portrait may not match hero, if custom portrait was set in map editor components.push_back(Component (Component::HERO_PORTRAIT, VLC->heroh->heroes[m13489val]->imageIndex, 0, 0)); if (!isCustom) iwText.addReplacement(VLC->heroh->heroes[m13489val]->name); break; case MISSION_KILL_CREATURE: { components.push_back(Component(stackToKill)); if (!isCustom) { addReplacements(iwText, text); } } break; case MISSION_ART: { MetaString loot; for (auto & elem : m5arts) { components.push_back(Component (Component::ARTIFACT, elem, 0, 0)); loot << "%s"; loot.addReplacement(MetaString::ART_NAMES, elem); } if (!isCustom) iwText.addReplacement(loot.buildList()); } break; case MISSION_ARMY: { MetaString loot; for (auto & elem : m6creatures) { components.push_back(Component(elem)); loot << "%s"; loot.addReplacement(elem); } if (!isCustom) iwText.addReplacement(loot.buildList()); } break; case MISSION_RESOURCES: { MetaString loot; for (int i = 0; i < 7; ++i) { if (m7resources[i]) { components.push_back(Component (Component::RESOURCE, i, m7resources[i], 0)); loot << "%d %s"; loot.addReplacement(m7resources[i]); loot.addReplacement(MetaString::RES_NAMES, i); } } if (!isCustom) iwText.addReplacement(loot.buildList()); } break; case MISSION_PLAYER: components.push_back(Component (Component::FLAG, m13489val, 0, 0)); if (!isCustom) iwText.addReplacement(VLC->generaltexth->colors[m13489val]); break; } }
PlayerAI_Actions PlayerAI::takeAction() { int px, py; PlayerAI_Actions action; /* player coodinates */ px = cd->xpos; py = cd->ypos; /* set map for pathfinding algorithm */ pathfind_alg.setMatrix(cd->mapx, cd->mapy, cd->terrain); pathfind_alg.setSecondMatrix(CLIENT_MATRIX_SIZE, CLIENT_MATRIX_SIZE, cd->dynamic_objects, cd->xpos - MAX_CLIENT_VIEW, cd->ypos - MAX_CLIENT_VIEW); /* if node update was received wait some more */ /* if no update is received for a long time take another action */ if (purpose != BASIC) if (sbx != px || sby != py) { sb_wait_count++; if (sb_wait_count == AI_RETRY_COUNT) { if (debug_AI) printf("[AI]Wait limit reached " "(now:%d,%d -> sb: %d,%d) \n", px, py, sbx, sby); purpose = BASIC; path->clear(); } else return NO_ACTION; } if (debug_AI) printf("[AI][%d,%d]Purpose: %s\n", px, py, AI_state_names[purpose]); cd->purpose = purpose; /* select a new action */ switch (purpose) { case BASIC: checkFood(10) || checkQuest() || checkStrongPlayer() || checkWeakPlayer() || tryToExplore(); break; case SEEKING_QUEST: if (!questExists()) purpose = BASIC; checkFood(20); break; case CHASING_PLAYER: checkFood(40) || checkQuest() || checkWeakPlayer(); break; case EXPLORING: checkFood(90) || checkQuest() || checkStrongPlayer() || checkWeakPlayer(); break; default: break; } /* move player */ action = moveAlongThePath(); if (action != NO_ACTION) return action; if (path->size() <= 1 && purpose == CHASING_PLAYER) { if (debug_AI) printf("[AI]Attack\n"); purpose = BASIC; if (path->size() == 1) { int opponent_x = path->getX(); int opponent_y = path->getY(); if (opponent_x == px + 1) return ATTACK_RIGHT; if (opponent_x == px - 1) return ATTACK_LEFT; if (opponent_y == py + 1) return ATTACK_DOWN; if (opponent_y == py - 1) return ATTACK_UP; } return ATTACK_UP; } /* check if last purpose is over */ if (path->empty() && purpose != BASIC) { if (purpose == SEEKING_FOOD && cd->map[MAX_CLIENT_VIEW][MAX_CLIENT_VIEW].type == CELL_OBJECT && cd->map[MAX_CLIENT_VIEW][MAX_CLIENT_VIEW].quantity > 0) { if (debug_AI) printf("[AI]Eat\n"); purpose = BASIC; return USE; } purpose = BASIC; } return NO_ACTION; }