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(); }
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); }
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())); } } }