mirror of
https://github.com/scummvm/scummvm.git
synced 2025-04-02 10:52:32 -04:00
186 lines
4.9 KiB
C++
186 lines
4.9 KiB
C++
/* 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 <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#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
|