/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "mm/mm1/game/encounter.h" #include "mm/mm1/data/monsters.h" #include "mm/mm1/maps/maps.h" #include "mm/mm1/events.h" #include "mm/mm1/globals.h" #include "mm/mm1/mm1.h" namespace MM { namespace MM1 { namespace Game { void Encounter::execute() { if (!g_globals->_encountersOn) return; Maps::Map &map = *g_maps->_currentMap; int comp, maxRand, maxVal; const Monster *monsterP; _bribeFleeCtr = _bribeAlignmentCtr = 0; _alignmentsChanged = 0; // In manual mode, the scripts have already set up // a list of monsters to use if (!_manual) { _monsterSummaries.clear(); _levelIndex = 0; } _totalLevels = _highestLevel = 0; _levelOffset = _monsterImgNum = _maxLevelForImg = _fleeThreshold = 0; for (uint i = 0; i < g_globals->_party.size(); ++i) { const Character &c = g_globals->_party[i]; _highestLevel = MAX(_highestLevel, (int)c._level._current); if (!(c._condition & (BAD_CONDITION | PARALYZED | UNCONSCIOUS))) _totalLevels = MIN(_totalLevels + c._level._current, 255); } _totalLevels /= 2; _highestLevel /= 2; bool firstLoop = !_manual; _manual = false; while (firstLoop || _levelIndex < _totalLevels) { randomAdjust(); firstLoop = false; maxRand = _levelOffset + _highestLevel; if (maxRand >= 2) { int highestRand = map[Maps::MAP_33]; maxRand = MIN(maxRand, highestRand); comp = getRandomNumber(maxRand); } else { comp = 1; } maxVal = map[Maps::MAP_47]; if (comp < maxVal) { comp = MIN(maxVal, 10); } assert(_monsterSummaries.size() < MAX_COMBAT_MONSTERS); _monsterNum = getRandomNumber(16); _monsterSummaries.push_back(MonsterSummary(_monsterNum, comp)); _monsterLevel = comp; _levelIndex += comp; if (_monsterSummaries.size() < MAX_COMBAT_MONSTERS) { if (_monsterSummaries.size() >= map[Maps::MAP_MAX_MONSTERS]) goto exit_loop; monsterP = getMonster(); maxVal = getRandomNumber(monsterP->_count); for (int i = 0; i < maxVal; ++i) { assert(!_monsterSummaries.empty()); _monsterSummaries.push_back(_monsterSummaries.back()); _levelIndex += _monsterSummaries.back()._level; if (_monsterSummaries.size() >= MAX_COMBAT_MONSTERS) goto exit_loop; if (_monsterSummaries.size() >= map[Maps::MAP_MAX_MONSTERS]) goto exit_loop; } } else { goto exit_loop; } } exit_loop: _monsterList.clear(); for (uint i = 0; i < _monsterSummaries.size(); ++i) { maxVal = (_monsterSummaries[i]._level - 1) * 16 + _monsterSummaries[i]._num; if (_monsterSummaries[i]._level < 1 || _monsterSummaries[i]._level > 12 || maxVal >= 196) { _monsterSummaries[i]._level = 10; _monsterSummaries[i]._num = getRandomNumber(15); } // Add monster details to list _monsterLevel = _monsterSummaries[i]._level; const Monster &srcMons = (*g_globals->_monsters)[_monsterSummaries[i]._num]; _monsterList.push_back(srcMons); Monster &mons = _monsterList.back(); mons._level = _monsterSummaries[i]._level; if (_monsterLevel > _maxLevelForImg) { _maxLevelForImg = _monsterLevel; _fleeThreshold = mons._fleeThreshold; _monsterImgNum = mons._imgNum; } } g_events->addView("Encounter"); } void Encounter::randomAdjust() { int rval = getRandomNumber(100); _levelOffset = 0; if (rval < 51) { } else if (rval < 71) _levelOffset += 1; else if (rval < 86) _levelOffset += 2; else if (rval < 96) _levelOffset += 3; else _levelOffset += 4; } const Monster *Encounter::getMonster() { assert(_monsterNum > 0 && _monsterLevel > 0); return &(*g_globals->_monsters)[_monsterNum + ((_monsterLevel - 1) * 16)]; } bool Encounter::checkSurroundParty() const { return getRandomNumber(100) > _fleeThreshold; } void Encounter::changeCharAlignment(Alignment align) { if (g_globals->_currCharacter->_alignment != align) { g_globals->_currCharacter->_alignment = align; ++_alignmentsChanged; } } void Encounter::clearMonsters() { _monsterSummaries.clear(); } void Encounter::addMonster(byte id, byte level) { _monsterSummaries.push_back(MonsterSummary(id, level)); } } // namespace Game } // namespace MM1 } // namespace MM