scummvm/engines/griffon/engine.cpp
2019-11-13 22:07:08 +01:00

341 lines
7.5 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
* Originally written by Syn9 in FreeBASIC with SDL
* http://syn9.thehideoutgames.com/index_backup.php
*
* Ported to plain C for GCW-Zero handheld by Dmitry Smagin
* http://github.com/dmitrysmagin/griffon_legend
*
*
* Programming/Graphics: Daniel "Syn9" Kennedy
* Music/Sound effects: David Turner
*
* Beta testing and gameplay design help:
* Deleter, Cha0s, Aether Fox, and Kiz
*
*/
#include "griffon/griffon.h"
#include "griffon/console.h"
#include "common/system.h"
namespace Griffon {
void Player::reset() {
px = 0;
py = 0;
opx = 0;
opy = 0;
walkDir = 0;
walkFrame = 0;
walkSpeed = 0;
attackFrame = 0;
attackSpeed = 0;
hp = 0;
maxHp = 0;
hpflash = 0;
level = 0;
maxLevel = 0;
sword = 0;
shield = 0;
armour = 0;
for (int i = 0; i < 5; i++) {
foundSpell[i] = 0;
spellCharge[i] = 0;
inventory[i] = 0;
}
attackStrength = 0;
spellDamage = 0;
swordDamage = 0;
exp = 0;
nextLevel = 0;
}
// copypaste from hRnd_CRT()
float GriffonEngine::RND() {
/* return between 0 and 1 (but never 1) */
return (float)_rnd->getRandomNumber(32767) * (1.0f / 32768.0f);
}
void GriffonEngine::mainLoop() {
swash();
if (_pmenu) {
haltSoundChannel(_menuChannel);
_pmenu = false;
}
do {
if (!_forcePause) {
updateAnims();
updateNPCs();
}
checkTrigger();
checkInputs();
if (!_forcePause)
handleWalking();
updateY();
drawView();
updateMusic();
_console->onFrame();
updateEngine();
} while (!_shouldQuit && !_gameEnd);
}
void GriffonEngine::updateEngine() {
g_system->updateScreen();
_ticksPassed = _ticks;
_ticks = g_system->getMillis();
_ticksPassed = _ticks - _ticksPassed;
_fpsr = (float)_ticksPassed / 24.0;
_fp++;
if (_ticks > _nextTicks) {
_nextTicks = _ticks + 1000;
_fps = _fp;
_fp = 0;
_secsInGame = _secsInGame + 1;
}
if (_attacking) {
_player.attackFrame += _player.attackSpeed * _fpsr;
if (_player.attackFrame >= 16) {
_attacking = false;
_player.attackFrame = 0;
_player.walkFrame = 0;
}
int pa = (int)(_player.attackFrame);
for (int i = 0; i <= pa; i++) {
if (!_playerAttackOfs[_player.walkDir][i].completed) {
_playerAttackOfs[_player.walkDir][i].completed = true;
float opx = _player.px;
float opy = _player.py;
_player.px += _playerAttackOfs[_player.walkDir][i].x;
_player.py += _playerAttackOfs[_player.walkDir][i].y;
int sx = (int)(_player.px / 2 + 6);
int sy = (int)(_player.py / 2 + 10);
uint32 *temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
uint32 bgc = *temp;
if (bgc > 0) {
_player.px = opx;
_player.py = opy;
}
}
}
_player.opx = _player.px;
_player.opy = _player.py;
checkHit();
if (_gameEnd)
return;
}
for (int i = 0; i < kMaxFloat; i++) {
if (_floatText[i].framesLeft > 0) {
float spd = 0.5 * _fpsr;
_floatText[i].framesLeft -= spd;
_floatText[i].y -= spd;
if (_floatText[i].framesLeft < 0)
_floatText[i].framesLeft = 0;
}
if (_floatIcon[i].framesLeft > 0) {
float spd = 0.5 * _fpsr;
_floatIcon[i].framesLeft -= spd;
_floatIcon[i].y -= spd;
if (_floatIcon[i].framesLeft < 0)
_floatIcon[i].framesLeft = 0;
}
}
if (_player.level == _player.maxLevel)
_player.exp = 0;
if (_player.exp >= _player.nextLevel) {
_player.level = _player.level + 1;
addFloatText("LEVEL UP!", _player.px + 16 - 36, _player.py + 16, 3);
_player.exp = _player.exp - _player.nextLevel;
_player.nextLevel = _player.nextLevel * 3 / 2; // 1.5
_player.maxHp = _player.maxHp + _player.level * 3;
if (_player.maxHp > 999)
_player.maxHp = 999;
_player.hp = _player.maxHp;
_player.swordDamage = _player.level * 14 / 10;
_player.spellDamage = _player.level * 13 / 10;
if (config.effects) {
int snd = playSound(_sfx[kSndPowerUp]);
setChannelVolume(snd, config.effectsVol);
}
}
_clipBg->copyRectToSurface(_clipBg2->getPixels(), _clipBg2->pitch, 0, 0, _clipBg2->w, _clipBg2->h);
Common::Rect rc;
rc.left = _player.px - 2;
rc.top = _player.py - 2;
rc.setWidth(5);
rc.setHeight(5);
_clipBg->fillRect(rc, 1000);
if (!_forcePause) {
for (int i = 0; i < 5; i++) {
if (_player.foundSpell[i])
_player.spellCharge[i] += 1 * _player.level * 0.01 * _fpsr;
if (_player.spellCharge[i] > 100)
_player.spellCharge[i] = 100;
}
if (_player.foundSpell[0]) {
_player.spellStrength += 3 * _player.level * .01 * _fpsr;
}
_player.attackStrength += (30 + 3 * (float)_player.level) / 50 * _fpsr;
}
if (_player.attackStrength > 100)
_player.attackStrength = 100;
if (_player.spellStrength > 100)
_player.spellStrength = 100;
_itemyloc += 0.75 * _fpsr;
while (_itemyloc >= 16)
_itemyloc -= 16;
if (_player.hp <= 0) {
theEnd();
_gameEnd = true;
return;
}
if (_roomLock) {
_roomLock = false;
for (int i = 1; i <= _lastNpc; i++)
if (_npcInfo[i].hp > 0)
_roomLock = true;
}
_cloudAngle += 0.1 * _fpsr;
while (_cloudAngle >= 360)
_cloudAngle = _cloudAngle - 360;
_player.hpflash = _player.hpflash + 0.1 * _fpsr;
if (_player.hpflash >= 2) {
_player.hpflash = 0;
_player.hpflashb = _player.hpflashb + 1;
if (_player.hpflashb == 2)
_player.hpflashb = 0;
if (config.effects && _player.hpflashb == 0 && _player.hp < _player.maxHp / 4) {
int snd = playSound(_sfx[kSndBeep]);
setChannelVolume(snd, config.effectsVol);
}
}
// _cloudsOn = false
if (_itemSelOn)
_player.itemselshade = _player.itemselshade + 2 * _fpsr;
if (_player.itemselshade > 24)
_player.itemselshade = 24;
for (int i = 0; i <= 4; i++)
if (_player.inventory[i] > 9)
_player.inventory[i] = 9;
}
void GriffonEngine::newGame() {
intro();
if (_shouldQuit)
return;
_player.reset();
_playera.reset();
memset(_scriptFlag, 0, sizeof(_scriptFlag));
memset(_objectMapFull, 0, sizeof(_objectMapFull));
memset(_roomLocks, 0, sizeof(_roomLocks));
_roomLocks[66] = 2;
_roomLocks[24] = 2;
_roomLocks[17] = 1;
_roomLocks[34] = 1;
_roomLocks[50] = 1;
_roomLocks[73] = 1;
_roomLocks[82] = 2;
_player.walkSpeed = 1.1f;
_animSpeed = 0.5f;
_attacking = false;
_player.attackSpeed = 1.5f;
_player.sword = 1;
_player.level = 1;
_player.maxLevel = 22;
_player.nextLevel = 50;
_player.shield = 1;
_player.armour = 1;
_player.hp = 14;
_player.maxHp = _player.hp;
_player.swordDamage = _player.level * 2;
_player.spellDamage = _player.level * 3 / 2;
_player.px = 15 * 16 - 4;
_player.py = 6 * 16 - 4;
_player.walkDir = 1;
_playingGardens = false;
_playingBoss = false;
_player.spellStrength = 0;
loadMap(2);
mainLoop();
}
} // end of namespace Griffon