void GameEngine::doBattle(Actor* atkr, Actor* atkd) {
	string heroHP = "HP: " + to_string(hero->getHP()) + "\n";
	lib.play("OnHit");

	int atkrDMG = atkr->getATK() - atkd->getActorDef().getDEF();
	int atkdDMG = atkd->getATK() - atkr->getActorDef().getDEF();

	atkr->doDMG(atkdDMG);
	string atkrEvent;
	if(atkrDMG > 0)
		atkrEvent = atkr->getActorDef().getDESC() + " attacked " + atkd->getActorDef().getDESC() + " for " + to_string(atkrDMG) + "!";
	else
		atkrEvent = atkr->getActorDef().getDESC() + " missed!";
	log.registerEvent(atkrEvent);

	atkd->doDMG(atkrDMG);
	string atkdEvent;
	if (atkrDMG > 0) {
		if (atkdDMG > 0)
			atkdEvent = atkd->getActorDef().getDESC() + " defended for " + to_string(atkdDMG) + "!";
		else
			atkdEvent = atkd->getActorDef().getDESC() + " couldn't defend!";
	}
	else
		atkdEvent = atkd->getActorDef().getDESC() + " missed!";
	log.registerEvent(atkdEvent);
	
	if (atkr->onDeath()) {
		if (atkr->isHero()) {
			lib.play("HeroOnDeath");
			killHero();
		}
		else
			killMonster(atkr->getLoc());
	}
	else if (atkd->onDeath()) {
		if (atkd->isHero()) {
			lib.play("HeroOnDeath");
			killHero();
		}
		else 
			killMonster(atkd->getLoc());
	}

	//Degrade armor / weapon
	invLog.degradeGear();
}
Exemple #2
0
void DarkMoonEngine::replaceMonster(int unit, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem) {
	uint8 flg = _levelBlockProperties[block].flags & 7;

	if (flg == 7 || _currentBlock == block || (flg && (_monsterProps[type].u30 || pos == 4)))
		return;

	for (int i = 0; i < 30; i++) {
		if (_monsters[i].block != block)
			continue;
		if (_monsters[i].pos == 4 || _monsterProps[_monsters[i].type].u30)
			return;
	}

	int index = -1;
	int maxDist = 0;

	for (int i = 0; i < 30; i++) {
		if (_monsters[i].hitPointsCur <= 0) {
			index = i;
			break;
		}

		if (_monsters[i].flags & 0x40)
			continue;

		// WORKAROUND for bug #3611077 (Dran's dragon transformation sequence triggered prematurely):
		// The boss level and the mindflayer level share the same monster data. If you hang around
		// long enough in the mindflayer level all 30 monster slots will be used up. When this
		// happens it will trigger the dragon transformation sequence when Dran is moved around by script.
		// We avoid removing Dran here by prefering monster slots occupied by monsters from another
		// sub level.
		if (_monsters[i].sub != _currentSub) {
			index = i;
			break;
		}

		int dist = getBlockDistance(_monsters[i].block, _currentBlock);

		if (dist > maxDist) {
			maxDist = dist;
			index = i;
		}
	}

	if (index == -1)
		return;

	if (_monsters[index].hitPointsCur > 0)
		killMonster(&_monsters[index], false);

	initMonster(index, unit, block, pos, dir, type, shpIndex, mode, h2, randItem, fixedItem);
}
Exemple #3
0
void DarkMoonEngine::replaceMonster(int unit, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem) {
	uint8 flg = _levelBlockProperties[block].flags & 7;

	if (flg == 7 || _currentBlock == block || (flg && (_monsterProps[type].u30 || pos == 4)))
		return;

	for (int i = 0; i < 30; i++) {
		if (_monsters[i].block != block)
			continue;
		if (_monsters[i].pos == 4 || _monsterProps[_monsters[i].type].u30)
			return;
	}

	int index = -1;
	int maxDist = 0;

	for (int i = 0; i < 30; i++) {
		if (_monsters[i].hitPointsCur <= 0) {
			index = i;
			break;
		}

		if (_monsters[i].flags & 0x40)
			continue;

		int dist = getBlockDistance(_monsters[i].block, _currentBlock);

		if (dist > maxDist) {
			maxDist = dist;
			index = i;
		}
	}

	if (index == -1)
		return;

	if (_monsters[index].hitPointsCur > 0)
		killMonster(&_monsters[index], false);

	initMonster(index, unit, block, pos, dir, type, shpIndex, mode, h2, randItem, fixedItem);
}
bool GameEngine::moveAI(Actor* monster) {
	//Death Curse damage
	if (monster->getSpell().getSpellType() == 5) {
		monster->doDMG(3);
		if (monster->getHP() <= 0)
			killMonster(monster->getLoc());
	}

	Point heroLoc = hero->getLoc();
	Point loc = monster->getLoc();
	int xDist = heroLoc.x() - loc.x();
	int yDist = heroLoc.y() - loc.y();
	int which = 0;

	Point dir(0, 0);

	//Choose direction
	if (xDist == 0 && yDist == 0)
		dir = Point(0, 0);
	else if (xDist == 0 && yDist != 0)
		dir = Point(0, yDist / abs(yDist));
	else if (xDist != 0 && yDist == 0)
		dir = Point(xDist / abs(xDist), 0);
	else if (xDist != 0 && yDist != 0)
		dir = Point(xDist / abs(xDist), yDist / abs(yDist));


	//Move monster based on whether it's close enough to the hero or not
	if (abs(xDist) + abs(yDist) < 5) {
		loc = loc + pickAIPoint(monster, dir, false);
		monster->gettingTired();
	}
	else
		loc = loc + pickAIPoint(monster, dir, true);

	//Don't move the monster if it's next to the hero, make it attack
	if (Point(abs(xDist), abs(yDist)) == Point(0, 1) || Point(abs(xDist), abs(yDist)) == Point(1, 0))
		return true; //Is going to attack hero
	else {
		//Update loc in map grid
		try {
			if (loc > Point(0, 0) && loc < Point(63, 63)) {
				if (moveableCell(map[loc.x()][loc.y()].getLoc())) {
					if (!monster->isTired()) {
						if (map[monster->getLoc().x()][monster->getLoc().y()].getSpell().getSpellType() != 4) { //If monster is in ice block, don't move
							//Move the monster
							map[monster->getLoc().x()][monster->getLoc().y()].setActor(NULL);
							monster->setLoc(loc);
							map[loc.x()][loc.y()].setActor(monster);
						}

						if (map[loc.x()][loc.y()].getSpell().getSpellType() == 1) { //Field of fire, damage monster if they're in the spell
							monster->doDMG(2);
							if (monster->getHP() <= 0)
								killMonster(monster->getLoc());
						}
						else if (map[loc.x()][loc.y()].getSpell().getSpellType() == 6) {
							monster->doDMG(10);
							log.registerEvent(monster->getActorDef().getDESC() + " triggered Fist of Katar!");
							if (monster->getHP() <= 0)
								killMonster(monster->getLoc());
							map[loc.x()][loc.y()].setSpell(Spell());
						}
					}
				}
			}
		}
		catch (int e) {
			OutputDebugString(to_string(e).c_str());
		}
		return false;
	}
}
//Spell stuff
void GameEngine::useSpell(Point mouseLoc) {
	Spell spell = invLog.getSpell(mouseLoc);

	if (spell.isUnlocked()) {
		if (hero->getMana() < spell.getCost())
			log.registerEvent("Not enough mana!");
		else {
			log.registerEvent(spell.getTitle() + " activated!");

			Point start = hero->getLoc() + Point(-1, -1);
			Point end = hero->getLoc() + Point(2, 2);

			int type = spell.getSpellType();
			switch (type) {
				case 1: //Field of fire
				{
					spell.setTurnActivated(turns);

					lib.loop_portion(start, end, [&](Point p) {
						map[p.x()][p.y()].setSpell(spell);
					});
					break;
				}
				case 2: //Death Rattle
				{
					lib.loop_portion(start, end, [&](Point p) {
						Actor* a = map[p.x()][p.y()].getActor();

						if (a != NULL) {
							Point relToHero = p - hero->getLoc();
							Point d(p.x() + relToHero.x(), p.y() + relToHero.y());
							
							a->doDMG(2);
							if (a->getHP() <= 0)
								killMonster(a->getLoc());

							if (moveableCell(d)) {
								map[p.x()][p.y()].setActor(NULL);
								a->setLoc(d);
								map[d.x()][d.y()].setActor(a);
							}
						}
					});
					break;
				}
				case 3: //Blessing of Katar
				{
					hero->changeHP(10);
					break;
				}
				case 4: //Ice Block
				{
					spell.setTurnActivated(turns);

					lib.loop_portion(start, end, [&](Point p) {
						map[p.x()][p.y()].setSpell(spell);
					});
					break;
				}
				case 5: //Death Curse
				{
					spell.setTurnActivated(turns);

					lib.loop_portion(start, end, [&](Point p) {
						Actor* a = map[p.x()][p.y()].getActor();
						if (a != NULL) {
							a->setSpell(spell);
						}
					});
					break;
				}
				case 6: //Fist of Katar
				{
					map[hero->getLoc().x()][hero->getLoc().y()].setSpell(spell);
					break;
				}
			}

			hero->changeMana(-spell.getCost());
			lib.play("Spell" + to_string(spell.getSpellType()));
		}
	}
}