Initial commit
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
/* 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 "ultima/ultima4/controllers/alpha_action_controller.h"
|
||||
#include "ultima/ultima4/events/event_handler.h"
|
||||
#include "ultima/ultima4/gfx/screen.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
bool AlphaActionController::keyPressed(int key) {
|
||||
if (Common::isLower(key))
|
||||
key = toupper(key);
|
||||
|
||||
if (key >= 'A' && key <= toupper(_lastValidLetter)) {
|
||||
_value = key - 'A';
|
||||
doneWaiting();
|
||||
} else {
|
||||
g_screen->screenMessage("\n%s", _prompt.c_str());
|
||||
g_screen->update();
|
||||
return KeyHandler::defaultHandler(key, nullptr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AlphaActionController::keybinder(KeybindingAction action) {
|
||||
if (action == KEYBIND_ESCAPE) {
|
||||
g_screen->screenMessage("\n");
|
||||
_value = -1;
|
||||
doneWaiting();
|
||||
}
|
||||
}
|
||||
|
||||
int AlphaActionController::get(char lastValidLetter, const Common::String &prompt, EventHandler *eh) {
|
||||
if (!eh)
|
||||
eh = eventHandler;
|
||||
|
||||
AlphaActionController ctrl(lastValidLetter, prompt);
|
||||
eh->pushController(&ctrl);
|
||||
return ctrl.waitFor();
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
52
engines/ultima/ultima4/controllers/alpha_action_controller.h
Normal file
52
engines/ultima/ultima4/controllers/alpha_action_controller.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_ALPHA_ACTION_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_ALPHA_ACTION_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/controller.h"
|
||||
#include "ultima/ultima4/events/event_handler.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
/**
|
||||
* A controller to handle input for commands requiring a letter
|
||||
* argument in the range 'a' - lastValidLetter.
|
||||
*/
|
||||
class AlphaActionController : public WaitableController<int> {
|
||||
private:
|
||||
char _lastValidLetter;
|
||||
Common::String _prompt;
|
||||
public:
|
||||
AlphaActionController(char letter, const Common::String &p) :
|
||||
WaitableController<int>(-1), _lastValidLetter(letter), _prompt(p) {}
|
||||
|
||||
bool keyPressed(int key) override;
|
||||
void keybinder(KeybindingAction action) override;
|
||||
|
||||
static int get(char lastValidLetter, const Common::String &prompt, EventHandler *eh = nullptr);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
123
engines/ultima/ultima4/controllers/camp_controller.cpp
Normal file
123
engines/ultima/ultima4/controllers/camp_controller.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/* 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 "ultima/ultima4/controllers/camp_controller.h"
|
||||
#include "ultima/ultima4/core/utils.h"
|
||||
#include "ultima/ultima4/filesys/savegame.h"
|
||||
#include "ultima/ultima4/map/mapmgr.h"
|
||||
#include "ultima/ultima4/ultima4.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
CampController::CampController() {
|
||||
MapId id;
|
||||
|
||||
/* setup camp (possible, but not for-sure combat situation */
|
||||
if (g_context->_location->_context & CTX_DUNGEON)
|
||||
id = MAP_CAMP_DNG;
|
||||
else
|
||||
id = MAP_CAMP_CON;
|
||||
|
||||
_map = getCombatMap(mapMgr->get(id));
|
||||
g_game->setMap(_map, true, nullptr, this);
|
||||
}
|
||||
|
||||
void CampController::init(Creature *m) {
|
||||
CombatController::init(m);
|
||||
_camping = true;
|
||||
}
|
||||
|
||||
void CampController::begin() {
|
||||
// make sure everyone's asleep
|
||||
for (int i = 0; i < g_context->_party->size(); i++)
|
||||
g_context->_party->member(i)->putToSleep();
|
||||
|
||||
CombatController::begin();
|
||||
|
||||
g_music->camp();
|
||||
|
||||
g_screen->screenMessage("Resting...\n");
|
||||
g_screen->screenDisableCursor();
|
||||
|
||||
EventHandler::wait_msecs(settings._campTime * 1000);
|
||||
|
||||
g_screen->screenEnableCursor();
|
||||
|
||||
/* Is the party ambushed during their rest? */
|
||||
if (settings._campingAlwaysCombat || (xu4_random(8) == 0)) {
|
||||
const Creature *m = creatureMgr->randomAmbushing();
|
||||
|
||||
g_music->playMapMusic();
|
||||
g_screen->screenMessage("Ambushed!\n");
|
||||
|
||||
/* create an ambushing creature (so it leaves a chest) */
|
||||
setCreature(g_context->_location->_prev->_map->addCreature(m, g_context->_location->_prev->_coords));
|
||||
|
||||
/* fill the creature table with creatures and place them */
|
||||
fillCreatureTable(m);
|
||||
placeCreatures();
|
||||
|
||||
/* creatures go first! */
|
||||
finishTurn();
|
||||
} else {
|
||||
/* Wake everyone up! */
|
||||
for (int i = 0; i < g_context->_party->size(); i++)
|
||||
g_context->_party->member(i)->wakeUp();
|
||||
|
||||
/* Make sure we've waited long enough for camping to be effective */
|
||||
bool healed = false;
|
||||
if (((g_ultima->_saveGame->_moves / CAMP_HEAL_INTERVAL) >= 0x10000) ||
|
||||
(((g_ultima->_saveGame->_moves / CAMP_HEAL_INTERVAL) & 0xffff) != g_ultima->_saveGame->_lastCamp))
|
||||
healed = heal();
|
||||
|
||||
g_screen->screenMessage(healed ? "Party Healed!\n" : "No effect.\n");
|
||||
g_ultima->_saveGame->_lastCamp = (g_ultima->_saveGame->_moves / CAMP_HEAL_INTERVAL) & 0xffff;
|
||||
|
||||
eventHandler->popController();
|
||||
g_game->exitToParentMap();
|
||||
g_music->fadeIn(CAMP_FADE_IN_TIME, true);
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void CampController::end(bool adjustKarma) {
|
||||
// wake everyone up!
|
||||
for (int i = 0; i < g_context->_party->size(); i++)
|
||||
g_context->_party->member(i)->wakeUp();
|
||||
CombatController::end(adjustKarma);
|
||||
}
|
||||
|
||||
bool CampController::heal() {
|
||||
// restore each party member to max mp, and restore some hp
|
||||
bool healed = false;
|
||||
for (int i = 0; i < g_context->_party->size(); i++) {
|
||||
PartyMember *m = g_context->_party->member(i);
|
||||
m->setMp(m->getMaxMp());
|
||||
if ((m->getHp() < m->getMaxHp()) && m->heal(HT_CAMPHEAL))
|
||||
healed = true;
|
||||
}
|
||||
|
||||
return healed;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
46
engines/ultima/ultima4/controllers/camp_controller.h
Normal file
46
engines/ultima/ultima4/controllers/camp_controller.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_CAMP_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_CAMP_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/combat_controller.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
#define CAMP_HEAL_INTERVAL 100 /* Number of moves before camping will heal the party */
|
||||
|
||||
class CampController : public CombatController {
|
||||
public:
|
||||
CampController();
|
||||
void init(Creature *m) override;
|
||||
void begin() override;
|
||||
void end(bool adjustKarma) override;
|
||||
|
||||
private:
|
||||
bool heal();
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
1076
engines/ultima/ultima4/controllers/combat_controller.cpp
Normal file
1076
engines/ultima/ultima4/controllers/combat_controller.cpp
Normal file
File diff suppressed because it is too large
Load Diff
286
engines/ultima/ultima4/controllers/combat_controller.h
Normal file
286
engines/ultima/ultima4/controllers/combat_controller.h
Normal file
@@ -0,0 +1,286 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_COMBAT_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_COMBAT_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/map/direction.h"
|
||||
#include "ultima/ultima4/map/map.h"
|
||||
#include "ultima/ultima4/controllers/controller.h"
|
||||
#include "ultima/ultima4/core/observer.h"
|
||||
#include "ultima/ultima4/core/types.h"
|
||||
#include "ultima/ultima4/filesys/savegame.h"
|
||||
#include "ultima/ultima4/game/creature.h"
|
||||
#include "ultima/ultima4/game/game.h"
|
||||
#include "ultima/ultima4/game/object.h"
|
||||
#include "ultima/ultima4/game/player.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
#define AREA_CREATURES 16
|
||||
#define AREA_PLAYERS 8
|
||||
|
||||
class CombatMap;
|
||||
class Creature;
|
||||
class MoveEvent;
|
||||
class Weapon;
|
||||
|
||||
typedef enum {
|
||||
CA_ATTACK,
|
||||
CA_CAST_SLEEP,
|
||||
CA_ADVANCE,
|
||||
CA_RANGED,
|
||||
CA_FLEE,
|
||||
CA_TELEPORT
|
||||
} CombatAction;
|
||||
|
||||
/**
|
||||
* CombatController class
|
||||
*/
|
||||
class CombatController : public Controller, public Observer<Party *, PartyEvent &>, public TurnCompleter {
|
||||
protected:
|
||||
CombatController();
|
||||
public:
|
||||
CombatController(CombatMap *m);
|
||||
CombatController(MapId id);
|
||||
virtual ~CombatController();
|
||||
|
||||
// Accessor Methods
|
||||
bool isCombatController() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a controller is made active
|
||||
*/
|
||||
void setActive() override;
|
||||
|
||||
bool isCamping() const;
|
||||
bool isWinOrLose() const;
|
||||
Direction getExitDir() const;
|
||||
byte getFocus() const;
|
||||
CombatMap *getMap() const;
|
||||
Creature *getCreature() const;
|
||||
PartyMemberVector *getParty();
|
||||
PartyMember *getCurrentPlayer();
|
||||
|
||||
void setExitDir(Direction d);
|
||||
void setCreature(Creature *);
|
||||
void setWinOrLose(bool worl = true);
|
||||
void showCombatMessage(bool show = true);
|
||||
|
||||
// Methods
|
||||
/**
|
||||
* Initializes the combat controller with combat information
|
||||
*/
|
||||
virtual void init(Creature *m);
|
||||
|
||||
/**
|
||||
* Initializes dungeon room combat
|
||||
*/
|
||||
void initDungeonRoom(int room, Direction from);
|
||||
|
||||
/**
|
||||
* Apply tile effects to all creatures depending on what they're standing on
|
||||
*/
|
||||
void applyCreatureTileEffects();
|
||||
|
||||
/**
|
||||
* Begin combat
|
||||
*/
|
||||
virtual void begin();
|
||||
virtual void end(bool adjustKarma);
|
||||
|
||||
/**
|
||||
* Fills the combat creature table with the creatures that the party will be facing.
|
||||
* The creature table only contains *which* creatures will be encountered and
|
||||
* *where* they are placed (by position in the table). Information like
|
||||
* hit points and creature status will be created when the creature is actually placed
|
||||
*/
|
||||
void fillCreatureTable(const Creature *creature);
|
||||
|
||||
/**
|
||||
* Generate the number of creatures in a group.
|
||||
*/
|
||||
int initialNumberOfCreatures(const Creature *creature) const;
|
||||
|
||||
/**
|
||||
* Returns true if the player has won.
|
||||
*/
|
||||
bool isWon() const;
|
||||
|
||||
/**
|
||||
* Returns true if the player has lost.
|
||||
*/
|
||||
bool isLost() const;
|
||||
|
||||
/**
|
||||
* Performs all of the creature's actions
|
||||
*/
|
||||
void moveCreatures();
|
||||
|
||||
/**
|
||||
* Places creatures on the map from the creature table and from the creature_start coords
|
||||
*/
|
||||
void placeCreatures();
|
||||
|
||||
/**
|
||||
* Places the party members on the map
|
||||
*/
|
||||
void placePartyMembers();
|
||||
|
||||
/**
|
||||
* Sets the active player for combat, showing which weapon they're weilding, etc.
|
||||
*/
|
||||
bool setActivePlayer(int player);
|
||||
bool attackHit(Creature *attacker, Creature *defender);
|
||||
virtual void awardLoot();
|
||||
|
||||
// attack functions
|
||||
void attack(Direction dir = DIR_NONE, int distance = 0);
|
||||
bool attackAt(const Coords &coords, PartyMember *attacker, int dir, int range, int distance);
|
||||
bool rangedAttack(const Coords &coords, Creature *attacker);
|
||||
void rangedMiss(const Coords &coords, Creature *attacker);
|
||||
bool returnWeaponToOwner(const Coords &coords, int distance, int dir, const Weapon *weapon);
|
||||
|
||||
/**
|
||||
* Static member functions
|
||||
*/
|
||||
static void attackFlash(const Coords &coords, MapTile tile, int timeFactor);
|
||||
static void attackFlash(const Coords &coords, const Common::String &tilename, int timeFactor);
|
||||
static void doScreenAnimationsWhilePausing(int timeFactor);
|
||||
|
||||
void keybinder(KeybindingAction action) override;
|
||||
|
||||
void finishTurn() override;
|
||||
|
||||
/**
|
||||
* Move a party member during combat and display the appropriate messages
|
||||
*/
|
||||
void movePartyMember(MoveEvent &event);
|
||||
void update(Party *party, PartyEvent &event) override;
|
||||
|
||||
// Properties
|
||||
protected:
|
||||
CombatMap *_map;
|
||||
|
||||
PartyMemberVector _party;
|
||||
byte _focus;
|
||||
|
||||
const Creature *_creatureTable[AREA_CREATURES];
|
||||
Creature *_creature;
|
||||
|
||||
bool _camping;
|
||||
bool _forceStandardEncounterSize;
|
||||
bool _placePartyOnMap;
|
||||
bool _placeCreaturesOnMap;
|
||||
bool _winOrLose;
|
||||
bool _showMessage;
|
||||
Direction _exitDir;
|
||||
|
||||
private:
|
||||
CombatController(const CombatController &);
|
||||
const CombatController &operator=(const CombatController &);
|
||||
|
||||
void init();
|
||||
};
|
||||
|
||||
extern CombatController *g_combat;
|
||||
|
||||
/**
|
||||
* CombatMap class
|
||||
*/
|
||||
class CombatMap : public Map {
|
||||
public:
|
||||
CombatMap();
|
||||
~CombatMap() override {}
|
||||
|
||||
/**
|
||||
* Returns a vector containing all of the creatures on the map
|
||||
*/
|
||||
CreatureVector getCreatures();
|
||||
|
||||
/**
|
||||
* Returns a vector containing all of the party members on the map
|
||||
*/
|
||||
PartyMemberVector getPartyMembers();
|
||||
|
||||
/**
|
||||
* Returns the party member at the given coords, if there is one,
|
||||
* nullptr if otherwise.
|
||||
*/
|
||||
PartyMember *partyMemberAt(Coords coords);
|
||||
|
||||
/**
|
||||
* Returns the creature at the given coords, if there is one,
|
||||
* nullptr if otherwise.
|
||||
*/
|
||||
Creature *creatureAt(Coords coords);
|
||||
|
||||
/**
|
||||
* Returns a valid combat map given the provided information
|
||||
*/
|
||||
static MapId mapForTile(const Tile *ground, const Tile *transport, Object *obj);
|
||||
|
||||
// Getters
|
||||
bool isDungeonRoom() const {
|
||||
return _dungeonRoom;
|
||||
}
|
||||
bool isAltarRoom() const {
|
||||
return _altarRoom != VIRT_NONE;
|
||||
}
|
||||
bool isContextual() const {
|
||||
return _contextual;
|
||||
}
|
||||
BaseVirtue getAltarRoom() const {
|
||||
return _altarRoom;
|
||||
}
|
||||
|
||||
// Setters
|
||||
void setAltarRoom(BaseVirtue ar) {
|
||||
_altarRoom = ar;
|
||||
}
|
||||
void setDungeonRoom(bool d) {
|
||||
_dungeonRoom = d;
|
||||
}
|
||||
void setContextual(bool c) {
|
||||
_contextual = c;
|
||||
}
|
||||
|
||||
// Properties
|
||||
protected:
|
||||
bool _dungeonRoom;
|
||||
BaseVirtue _altarRoom;
|
||||
bool _contextual;
|
||||
|
||||
public:
|
||||
Coords creature_start[AREA_CREATURES];
|
||||
Coords player_start[AREA_PLAYERS];
|
||||
};
|
||||
|
||||
bool isCombatMap(Map *punknown);
|
||||
CombatMap *getCombatMap(Map *punknown = nullptr);
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
82
engines/ultima/ultima4/controllers/controller.cpp
Normal file
82
engines/ultima/ultima4/controllers/controller.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/* 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 "ultima/ultima4/controllers/controller.h"
|
||||
#include "ultima/ultima4/events/event_handler.h"
|
||||
#include "engines/engine.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
Controller::Controller(int timerInterval) {
|
||||
this->_timerInterval = timerInterval;
|
||||
}
|
||||
|
||||
Controller::~Controller() {
|
||||
}
|
||||
|
||||
bool Controller::notifyKeyPressed(int key) {
|
||||
bool processed = KeyHandler::globalHandler(key);
|
||||
if (!processed)
|
||||
processed = keyPressed(key);
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
bool Controller::notifyMousePress(const Common::Point &mousePos) {
|
||||
return mousePressed(mousePos);
|
||||
}
|
||||
|
||||
|
||||
int Controller::getTimerInterval() {
|
||||
return _timerInterval;
|
||||
}
|
||||
|
||||
void Controller::setActive() {
|
||||
// By default, only the Escape action is turned on for controllers,
|
||||
// to allow the different sorts of input prompts to be aborted
|
||||
MetaEngine::setKeybindingMode(KBMODE_MINIMAL);
|
||||
}
|
||||
|
||||
void Controller::timerFired() {
|
||||
}
|
||||
|
||||
void Controller::timerCallback(void *data) {
|
||||
Controller *controller = static_cast<Controller *>(data);
|
||||
controller->timerFired();
|
||||
}
|
||||
|
||||
bool Controller::shouldQuit() const {
|
||||
return g_engine->shouldQuit();
|
||||
}
|
||||
|
||||
void Controller_startWait() {
|
||||
eventHandler->run();
|
||||
eventHandler->setControllerDone(false);
|
||||
eventHandler->popController();
|
||||
}
|
||||
|
||||
void Controller_endWait() {
|
||||
eventHandler->setControllerDone();
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
167
engines/ultima/ultima4/controllers/controller.h
Normal file
167
engines/ultima/ultima4/controllers/controller.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/metaengine.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
/**
|
||||
* A generic controller base class. Controllers are classes that
|
||||
* contain the logic for responding to external events (e.g. keyboard,
|
||||
* mouse, timers).
|
||||
*/
|
||||
class Controller {
|
||||
public:
|
||||
Controller(int timerInterval = 1);
|
||||
virtual ~Controller();
|
||||
|
||||
/* methods for interacting with event manager */
|
||||
virtual bool isCombatController() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The event manager will call this method to notify the active
|
||||
* controller that a key has been pressed. The key will be passed on
|
||||
* to the virtual keyPressed method.
|
||||
*/
|
||||
bool notifyKeyPressed(int key);
|
||||
|
||||
/**
|
||||
* The event manager will call this method to notify that
|
||||
* the left button was clicked
|
||||
*/
|
||||
bool notifyMousePress(const Common::Point &mousePos);
|
||||
|
||||
int getTimerInterval();
|
||||
|
||||
/**
|
||||
* A simple adapter to make a timer callback into a controller method
|
||||
* call.
|
||||
*/
|
||||
static void timerCallback(void *data);
|
||||
|
||||
/** control methods subclasses may want to override */
|
||||
|
||||
/**
|
||||
* Called when a controller is made active
|
||||
*/
|
||||
virtual void setActive();
|
||||
|
||||
/**
|
||||
* Key was pressed
|
||||
*/
|
||||
virtual bool keyPressed(int key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mouse button was pressed
|
||||
*/
|
||||
virtual bool mousePressed(const Common::Point &mousePos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles keybinder actions
|
||||
*/
|
||||
virtual void keybinder(KeybindingAction action) {}
|
||||
|
||||
/**
|
||||
* The default timerFired handler for a controller. By default,
|
||||
* timers are ignored, but subclasses can override this method and it
|
||||
* will be called every <interval> 1/4 seconds.
|
||||
*/
|
||||
virtual void timerFired();
|
||||
|
||||
/**
|
||||
* Returns true if game should quit
|
||||
*/
|
||||
bool shouldQuit() const;
|
||||
private:
|
||||
int _timerInterval;
|
||||
};
|
||||
|
||||
// helper functions for the waitable controller; they just avoid
|
||||
// having eventhandler dependencies in this header file
|
||||
void Controller_startWait();
|
||||
void Controller_endWait();
|
||||
|
||||
/**
|
||||
* Class template for controllers that can be "waited for".
|
||||
* Subclasses should set the value variable and call doneWaiting when
|
||||
* the controller has completed.
|
||||
*/
|
||||
template<class T>
|
||||
class WaitableController : public Controller {
|
||||
private:
|
||||
bool _exitWhenDone;
|
||||
T _defaultValue;
|
||||
protected:
|
||||
T _value;
|
||||
void doneWaiting() {
|
||||
if (_exitWhenDone)
|
||||
Controller_endWait();
|
||||
}
|
||||
public:
|
||||
WaitableController(T defaultValue) : _defaultValue(defaultValue),
|
||||
_value(defaultValue), _exitWhenDone(false) {}
|
||||
|
||||
virtual T getValue() {
|
||||
return shouldQuit() ? _defaultValue : _value;
|
||||
}
|
||||
|
||||
virtual T waitFor() {
|
||||
_exitWhenDone = true;
|
||||
Controller_startWait();
|
||||
return getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mouse button was pressed
|
||||
*/
|
||||
virtual bool mousePressed(const Common::Point &mousePos) {
|
||||
// Treat mouse clicks as an abort
|
||||
doneWaiting();
|
||||
_value = _defaultValue;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class TurnCompleter {
|
||||
public:
|
||||
virtual ~TurnCompleter() {
|
||||
}
|
||||
virtual void finishTurn() = 0;
|
||||
|
||||
virtual void finishTurnAfterCombatEnds() {
|
||||
finishTurn();
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
862
engines/ultima/ultima4/controllers/game_controller.cpp
Normal file
862
engines/ultima/ultima4/controllers/game_controller.cpp
Normal file
@@ -0,0 +1,862 @@
|
||||
/* 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 "ultima/ultima4/controllers/game_controller.h"
|
||||
#include "ultima/ultima4/core/config.h"
|
||||
#include "ultima/ultima4/core/debugger.h"
|
||||
#include "ultima/ultima4/core/utils.h"
|
||||
#include "ultima/ultima4/filesys/savegame.h"
|
||||
#include "ultima/ultima4/game/game.h"
|
||||
#include "ultima/ultima4/game/context.h"
|
||||
#include "ultima/ultima4/game/death.h"
|
||||
#include "ultima/ultima4/game/moongate.h"
|
||||
#include "ultima/ultima4/views/stats.h"
|
||||
#include "ultima/ultima4/gfx/imagemgr.h"
|
||||
#include "ultima/ultima4/gfx/screen.h"
|
||||
#include "ultima/ultima4/map/annotation.h"
|
||||
#include "ultima/ultima4/map/city.h"
|
||||
#include "ultima/ultima4/map/dungeon.h"
|
||||
#include "ultima/ultima4/map/mapmgr.h"
|
||||
#include "ultima/ultima4/map/shrine.h"
|
||||
#include "ultima/ultima4/ultima4.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
GameController *g_game = nullptr;
|
||||
|
||||
static const MouseArea MOUSE_AREAS[] = {
|
||||
{ 3, { { 8, 8 }, { 8, 184 }, { 96, 96 } }, MC_WEST, DIR_WEST },
|
||||
{ 3, { { 8, 8 }, { 184, 8 }, { 96, 96 } }, MC_NORTH, DIR_NORTH },
|
||||
{ 3, { { 184, 8 }, { 184, 184 }, { 96, 96 } }, MC_EAST, DIR_EAST },
|
||||
{ 3, { { 8, 184 }, { 184, 184 }, { 96, 96 } }, MC_SOUTH, DIR_SOUTH },
|
||||
{ 0, { { 0, 0 }, { 0, 0 }, { 0, 0 } }, MC_NORTH, DIR_NONE }
|
||||
};
|
||||
|
||||
GameController::GameController() :
|
||||
_mapArea(BORDER_WIDTH, BORDER_HEIGHT, VIEWPORT_W, VIEWPORT_H),
|
||||
_paused(false), _combatFinished(false), _pausedTimer(0) {
|
||||
g_game = this;
|
||||
}
|
||||
|
||||
void GameController::initScreen() {
|
||||
Image *screen = imageMgr->get("screen")->_image;
|
||||
|
||||
screen->fillRect(0, 0, screen->width(), screen->height(), 0, 0, 0);
|
||||
g_screen->update();
|
||||
}
|
||||
|
||||
void GameController::initScreenWithoutReloadingState() {
|
||||
g_music->playMapMusic();
|
||||
imageMgr->get(BKGD_BORDERS)->_image->draw(0, 0);
|
||||
g_context->_stats->update(); /* draw the party stats */
|
||||
|
||||
g_screen->screenMessage("Press Alt-h for help\n");
|
||||
g_screen->screenPrompt();
|
||||
|
||||
eventHandler->pushMouseAreaSet(MOUSE_AREAS);
|
||||
|
||||
eventHandler->setScreenUpdate(&gameUpdateScreen);
|
||||
}
|
||||
|
||||
void GameController::init() {
|
||||
initScreen();
|
||||
|
||||
// initialize the state of the global game context
|
||||
g_context->_line = TEXT_AREA_H - 1;
|
||||
g_context->_col = 0;
|
||||
g_context->_stats = new StatsArea();
|
||||
g_context->_moonPhase = 0;
|
||||
g_context->_windDirection = DIR_NORTH;
|
||||
g_context->_windCounter = 0;
|
||||
g_context->_windLock = false;
|
||||
g_context->_aura = new Aura();
|
||||
g_context->_horseSpeed = 0;
|
||||
g_context->_opacity = 1;
|
||||
g_context->_lastCommandTime = g_system->getMillis();
|
||||
g_context->_lastShip = nullptr;
|
||||
}
|
||||
|
||||
void GameController::setMap(Map *map, bool saveLocation, const Portal *portal, TurnCompleter *turnCompleter) {
|
||||
int viewMode;
|
||||
LocationContext context;
|
||||
int activePlayer = g_context->_party->getActivePlayer();
|
||||
MapCoords coords;
|
||||
|
||||
if (!turnCompleter)
|
||||
turnCompleter = this;
|
||||
|
||||
if (portal)
|
||||
coords = portal->_start;
|
||||
else
|
||||
coords = MapCoords(map->_width / 2, map->_height / 2);
|
||||
|
||||
/* If we don't want to save the location, then just return to the previous location,
|
||||
as there may still be ones in the stack we want to keep */
|
||||
if (!saveLocation)
|
||||
exitToParentMap();
|
||||
|
||||
switch (map->_type) {
|
||||
case Map::WORLD:
|
||||
context = CTX_WORLDMAP;
|
||||
viewMode = VIEW_NORMAL;
|
||||
break;
|
||||
case Map::DUNGEON:
|
||||
context = CTX_DUNGEON;
|
||||
viewMode = VIEW_DUNGEON;
|
||||
if (portal)
|
||||
g_ultima->_saveGame->_orientation = DIR_EAST;
|
||||
break;
|
||||
case Map::COMBAT:
|
||||
coords = MapCoords(-1, -1); /* set these to -1 just to be safe; we don't need them */
|
||||
context = CTX_COMBAT;
|
||||
viewMode = VIEW_NORMAL;
|
||||
activePlayer = -1; /* different active player for combat, defaults to 'None' */
|
||||
break;
|
||||
case Map::SHRINE:
|
||||
context = CTX_SHRINE;
|
||||
viewMode = VIEW_NORMAL;
|
||||
break;
|
||||
case Map::CITY:
|
||||
default:
|
||||
context = CTX_CITY;
|
||||
viewMode = VIEW_NORMAL;
|
||||
break;
|
||||
}
|
||||
g_context->_location = new Location(coords, map, viewMode, context, turnCompleter, g_context->_location);
|
||||
g_context->_location->addObserver(this);
|
||||
g_context->_party->setActivePlayer(activePlayer);
|
||||
#ifdef IOS_ULTIMA4
|
||||
U4IOS::updateGameControllerContext(c->location->context);
|
||||
#endif
|
||||
|
||||
/* now, actually set our new tileset */
|
||||
_mapArea.setTileset(map->_tileSet);
|
||||
|
||||
if (isCity(map)) {
|
||||
City *city = dynamic_cast<City *>(map);
|
||||
assert(city);
|
||||
city->addPeople();
|
||||
}
|
||||
}
|
||||
|
||||
int GameController::exitToParentMap() {
|
||||
if (!g_context->_location)
|
||||
return 0;
|
||||
|
||||
if (g_context->_location->_prev != nullptr) {
|
||||
// Create the balloon for Hythloth
|
||||
if (g_context->_location->_map->_id == MAP_HYTHLOTH)
|
||||
createBalloon(g_context->_location->_prev->_map);
|
||||
|
||||
// free map info only if previous location was on a different map
|
||||
if (g_context->_location->_prev->_map != g_context->_location->_map) {
|
||||
g_context->_location->_map->_annotations->clear();
|
||||
g_context->_location->_map->clearObjects();
|
||||
|
||||
/* quench the torch of we're on the world map */
|
||||
if (g_context->_location->_prev->_map->isWorldMap())
|
||||
g_context->_party->quenchTorch();
|
||||
}
|
||||
locationFree(&g_context->_location);
|
||||
|
||||
// restore the tileset to the one the current map uses
|
||||
_mapArea.setTileset(g_context->_location->_map->_tileSet);
|
||||
#ifdef IOS_ULTIMA4
|
||||
U4IOS::updateGameControllerContext(c->location->context);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GameController::finishTurn() {
|
||||
g_context->_lastCommandTime = g_system->getMillis();
|
||||
Creature *attacker = nullptr;
|
||||
|
||||
while (1) {
|
||||
|
||||
/* adjust food and moves */
|
||||
g_context->_party->endTurn();
|
||||
|
||||
/* count down the aura, if there is one */
|
||||
g_context->_aura->passTurn();
|
||||
|
||||
gameCheckHullIntegrity();
|
||||
|
||||
/* update party stats */
|
||||
//c->stats->setView(STATS_PARTY_OVERVIEW);
|
||||
|
||||
g_screen->screenUpdate(&this->_mapArea, true, false);
|
||||
g_screen->screenWait(1);
|
||||
|
||||
/* Creatures cannot spawn, move or attack while the avatar is on the balloon */
|
||||
if (!g_context->_party->isFlying()) {
|
||||
|
||||
// apply effects from tile avatar is standing on
|
||||
g_context->_party->applyEffect(g_context->_location->_map->tileTypeAt(g_context->_location->_coords, WITH_GROUND_OBJECTS)->getEffect());
|
||||
|
||||
// WORKAROUND: This fixes infinite combat loop at the Shrine of Humility.
|
||||
// I presume the original had code to show the game screen after combat
|
||||
// without doing all the end turn logic
|
||||
if (!_combatFinished) {
|
||||
// Move creatures and see if something is attacking the avatar
|
||||
attacker = g_context->_location->_map->moveObjects(g_context->_location->_coords);
|
||||
|
||||
// Something's attacking! Start combat!
|
||||
if (attacker) {
|
||||
gameCreatureAttack(attacker);
|
||||
return;
|
||||
}
|
||||
|
||||
// cleanup old creatures and spawn new ones
|
||||
creatureCleanup();
|
||||
checkRandomCreatures();
|
||||
checkBridgeTrolls();
|
||||
} else {
|
||||
_combatFinished = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* update map annotations */
|
||||
g_context->_location->_map->_annotations->passTurn();
|
||||
|
||||
if (!g_context->_party->isImmobilized())
|
||||
break;
|
||||
|
||||
if (g_context->_party->isDead()) {
|
||||
g_death->start(0);
|
||||
return;
|
||||
} else {
|
||||
g_screen->screenMessage("Zzzzzz\n");
|
||||
g_screen->screenWait(4);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_context->_location->_context == CTX_DUNGEON) {
|
||||
Dungeon *dungeon = dynamic_cast<Dungeon *>(g_context->_location->_map);
|
||||
assert(dungeon);
|
||||
|
||||
if (g_context->_party->getTorchDuration() <= 0)
|
||||
g_screen->screenMessage("It's Dark!\n");
|
||||
else
|
||||
g_context->_party->burnTorch();
|
||||
|
||||
/* handle dungeon traps */
|
||||
if (dungeon->currentToken() == DUNGEON_TRAP) {
|
||||
dungeonHandleTrap((TrapType)dungeon->currentSubToken());
|
||||
// a little kludgey to have a second test for this
|
||||
// right here. But without it you can survive an
|
||||
// extra turn after party death and do some things
|
||||
// that could cause a crash, like Hole up and Camp.
|
||||
if (g_context->_party->isDead()) {
|
||||
g_death->start(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* draw a prompt */
|
||||
g_screen->screenPrompt();
|
||||
//g_screen->screenRedrawTextArea(TEXT_AREA_X, TEXT_AREA_Y, TEXT_AREA_W, TEXT_AREA_H);
|
||||
}
|
||||
|
||||
void GameController::flashTile(const Coords &coords, MapTile tile, int frames) {
|
||||
g_context->_location->_map->_annotations->add(coords, tile, true);
|
||||
|
||||
g_screen->screenTileUpdate(&g_game->_mapArea, coords);
|
||||
|
||||
g_screen->screenWait(frames);
|
||||
g_context->_location->_map->_annotations->remove(coords, tile);
|
||||
|
||||
g_screen->screenTileUpdate(&g_game->_mapArea, coords, false);
|
||||
}
|
||||
|
||||
void GameController::flashTile(const Coords &coords, const Common::String &tilename, int timeFactor) {
|
||||
Tile *tile = g_context->_location->_map->_tileSet->getByName(tilename);
|
||||
assertMsg(tile, "no tile named '%s' found in tileset", tilename.c_str());
|
||||
flashTile(coords, tile->getId(), timeFactor);
|
||||
}
|
||||
|
||||
void GameController::update(Party *party, PartyEvent &event) {
|
||||
int i;
|
||||
|
||||
switch (event._type) {
|
||||
case PartyEvent::LOST_EIGHTH:
|
||||
// inform a player he has lost zero or more eighths of avatarhood.
|
||||
g_screen->screenMessage("\n %cThou hast lost\n an eighth!%c\n", FG_YELLOW, FG_WHITE);
|
||||
break;
|
||||
case PartyEvent::ADVANCED_LEVEL:
|
||||
g_screen->screenMessage("\n%c%s\nThou art now Level %d%c\n", FG_YELLOW, event._player->getName().c_str(), event._player->getRealLevel(), FG_WHITE);
|
||||
gameSpellEffect('r', -1, SOUND_MAGIC); // Same as resurrect spell
|
||||
break;
|
||||
case PartyEvent::STARVING:
|
||||
g_screen->screenMessage("\n%cStarving!!!%c\n", FG_YELLOW, FG_WHITE);
|
||||
/* FIXME: add sound effect here */
|
||||
|
||||
// 2 damage to each party member for starving!
|
||||
for (i = 0; i < g_ultima->_saveGame->_members; i++)
|
||||
g_context->_party->member(i)->applyDamage(2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::update(Location *location, MoveEvent &event) {
|
||||
switch (location->_map->_type) {
|
||||
case Map::DUNGEON:
|
||||
avatarMovedInDungeon(event);
|
||||
break;
|
||||
case Map::COMBAT: {
|
||||
// FIXME: let the combat controller handle it
|
||||
CombatController *ctl = dynamic_cast<CombatController *>(eventHandler->getController());
|
||||
assert(ctl);
|
||||
ctl->movePartyMember(event);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
avatarMoved(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::setActive() {
|
||||
// The game controller has the keybindings enabled
|
||||
MetaEngine::setKeybindingMode(KBMODE_NORMAL);
|
||||
}
|
||||
|
||||
void GameController::keybinder(KeybindingAction action) {
|
||||
MetaEngine::executeAction(action);
|
||||
}
|
||||
|
||||
bool GameController::mousePressed(const Common::Point &mousePos) {
|
||||
const MouseArea *area = eventHandler->mouseAreaForPoint(mousePos.x, mousePos.y);
|
||||
|
||||
if (area) {
|
||||
keybinder(KEYBIND_INTERACT);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GameController::initMoons() {
|
||||
int trammelphase = g_ultima->_saveGame->_trammelPhase,
|
||||
feluccaphase = g_ultima->_saveGame->_feluccaPhase;
|
||||
|
||||
assertMsg(g_context != nullptr, "Game context doesn't exist!");
|
||||
assertMsg(g_ultima->_saveGame != nullptr, "Savegame doesn't exist!");
|
||||
//assertMsg(mapIsWorldMap(c->location->map) && c->location->viewMode == VIEW_NORMAL, "Can only call gameInitMoons() from the world map!");
|
||||
|
||||
g_ultima->_saveGame->_trammelPhase = g_ultima->_saveGame->_feluccaPhase = 0;
|
||||
g_context->_moonPhase = 0;
|
||||
|
||||
while ((g_ultima->_saveGame->_trammelPhase != trammelphase) ||
|
||||
(g_ultima->_saveGame->_feluccaPhase != feluccaphase))
|
||||
updateMoons(false);
|
||||
}
|
||||
|
||||
void GameController::updateMoons(bool showmoongates) {
|
||||
int realMoonPhase,
|
||||
oldTrammel,
|
||||
trammelSubphase;
|
||||
const Coords *gate;
|
||||
|
||||
if (g_context->_location->_map->isWorldMap()) {
|
||||
oldTrammel = g_ultima->_saveGame->_trammelPhase;
|
||||
|
||||
if (++g_context->_moonPhase >= MOON_PHASES * MOON_SECONDS_PER_PHASE * 4)
|
||||
g_context->_moonPhase = 0;
|
||||
|
||||
trammelSubphase = g_context->_moonPhase % (MOON_SECONDS_PER_PHASE * 4 * 3);
|
||||
realMoonPhase = (g_context->_moonPhase / (4 * MOON_SECONDS_PER_PHASE));
|
||||
|
||||
g_ultima->_saveGame->_trammelPhase = realMoonPhase / 3;
|
||||
g_ultima->_saveGame->_feluccaPhase = realMoonPhase % 8;
|
||||
|
||||
if (g_ultima->_saveGame->_trammelPhase > 7)
|
||||
g_ultima->_saveGame->_trammelPhase = 7;
|
||||
|
||||
if (showmoongates) {
|
||||
/* update the moongates if trammel changed */
|
||||
if (trammelSubphase == 0) {
|
||||
gate = g_moongates->getGateCoordsForPhase(oldTrammel);
|
||||
if (gate)
|
||||
g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x40));
|
||||
gate = g_moongates->getGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
|
||||
if (gate)
|
||||
g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x40));
|
||||
} else if (trammelSubphase == 1) {
|
||||
gate = g_moongates->getGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
|
||||
if (gate) {
|
||||
g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x40));
|
||||
g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x41));
|
||||
}
|
||||
} else if (trammelSubphase == 2) {
|
||||
gate = g_moongates->getGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
|
||||
if (gate) {
|
||||
g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x41));
|
||||
g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x42));
|
||||
}
|
||||
} else if (trammelSubphase == 3) {
|
||||
gate = g_moongates->getGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
|
||||
if (gate) {
|
||||
g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x42));
|
||||
g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x43));
|
||||
}
|
||||
} else if ((trammelSubphase > 3) && (trammelSubphase < (MOON_SECONDS_PER_PHASE * 4 * 3) - 3)) {
|
||||
gate = g_moongates->getGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
|
||||
if (gate) {
|
||||
g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x43));
|
||||
g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x43));
|
||||
}
|
||||
} else if (trammelSubphase == (MOON_SECONDS_PER_PHASE * 4 * 3) - 3) {
|
||||
gate = g_moongates->getGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
|
||||
if (gate) {
|
||||
g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x43));
|
||||
g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x42));
|
||||
}
|
||||
} else if (trammelSubphase == (MOON_SECONDS_PER_PHASE * 4 * 3) - 2) {
|
||||
gate = g_moongates->getGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
|
||||
if (gate) {
|
||||
g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x42));
|
||||
g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x41));
|
||||
}
|
||||
} else if (trammelSubphase == (MOON_SECONDS_PER_PHASE * 4 * 3) - 1) {
|
||||
gate = g_moongates->getGateCoordsForPhase(g_ultima->_saveGame->_trammelPhase);
|
||||
if (gate) {
|
||||
g_context->_location->_map->_annotations->remove(*gate, g_context->_location->_map->translateFromRawTileIndex(0x41));
|
||||
g_context->_location->_map->_annotations->add(*gate, g_context->_location->_map->translateFromRawTileIndex(0x40));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::avatarMoved(MoveEvent &event) {
|
||||
if (event._userEvent) {
|
||||
|
||||
// is filterMoveMessages even used? it doesn't look like the option is hooked up in the configuration menu
|
||||
if (!settings._filterMoveMessages) {
|
||||
switch (g_context->_transportContext) {
|
||||
case TRANSPORT_FOOT:
|
||||
case TRANSPORT_HORSE:
|
||||
g_screen->screenMessage("%s\n", getDirectionName(event._dir));
|
||||
break;
|
||||
case TRANSPORT_SHIP:
|
||||
if (event._result & MOVE_TURNED)
|
||||
g_screen->screenMessage("Turn %s!\n", getDirectionName(event._dir));
|
||||
else if (event._result & MOVE_SLOWED)
|
||||
g_screen->screenMessage("%cSlow progress!%c\n", FG_GREY, FG_WHITE);
|
||||
else
|
||||
g_screen->screenMessage("Sail %s!\n", getDirectionName(event._dir));
|
||||
break;
|
||||
case TRANSPORT_BALLOON:
|
||||
g_screen->screenMessage("%cDrift Only!%c\n", FG_GREY, FG_WHITE);
|
||||
break;
|
||||
default:
|
||||
error("bad transportContext %d in avatarMoved()", g_context->_transportContext);
|
||||
}
|
||||
}
|
||||
|
||||
/* movement was blocked */
|
||||
if (event._result & MOVE_BLOCKED) {
|
||||
|
||||
/* if shortcuts are enabled, try them! */
|
||||
if (settings._shortcutCommands) {
|
||||
MapCoords new_coords = g_context->_location->_coords;
|
||||
MapTile *tile;
|
||||
|
||||
new_coords.move(event._dir, g_context->_location->_map);
|
||||
tile = g_context->_location->_map->tileAt(new_coords, WITH_OBJECTS);
|
||||
|
||||
if (tile->getTileType()->isDoor()) {
|
||||
g_debugger->openAt(new_coords);
|
||||
event._result = (MoveResult)(MOVE_SUCCEEDED | MOVE_END_TURN);
|
||||
} else if (tile->getTileType()->isLockedDoor()) {
|
||||
g_debugger->jimmyAt(new_coords);
|
||||
event._result = (MoveResult)(MOVE_SUCCEEDED | MOVE_END_TURN);
|
||||
} /*else if (mapPersonAt(c->location->map, new_coords) != nullptr) {
|
||||
talkAtCoord(newx, newy, 1, nullptr);
|
||||
event.result = MOVE_SUCCEEDED | MOVE_END_TURN;
|
||||
}*/
|
||||
}
|
||||
|
||||
/* if we're still blocked */
|
||||
if ((event._result & MOVE_BLOCKED) && !settings._filterMoveMessages) {
|
||||
soundPlay(SOUND_BLOCKED, false);
|
||||
g_screen->screenMessage("%cBlocked!%c\n", FG_GREY, FG_WHITE);
|
||||
}
|
||||
} else if (g_context->_transportContext == TRANSPORT_FOOT || g_context->_transportContext == TRANSPORT_HORSE) {
|
||||
/* movement was slowed */
|
||||
if (event._result & MOVE_SLOWED) {
|
||||
soundPlay(SOUND_WALK_SLOWED);
|
||||
g_screen->screenMessage("%cSlow progress!%c\n", FG_GREY, FG_WHITE);
|
||||
} else {
|
||||
soundPlay(SOUND_WALK_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* exited map */
|
||||
if (event._result & MOVE_EXIT_TO_PARENT) {
|
||||
g_screen->screenMessage("%cLeaving...%c\n", FG_GREY, FG_WHITE);
|
||||
exitToParentMap();
|
||||
g_music->playMapMusic();
|
||||
}
|
||||
|
||||
/* things that happen while not on board the balloon */
|
||||
if (g_context->_transportContext & ~TRANSPORT_BALLOON)
|
||||
checkSpecialCreatures(event._dir);
|
||||
/* things that happen while on foot or horseback */
|
||||
if ((g_context->_transportContext & TRANSPORT_FOOT_OR_HORSE) &&
|
||||
!(event._result & (MOVE_SLOWED | MOVE_BLOCKED))) {
|
||||
if (checkMoongates())
|
||||
event._result = (MoveResult)(MOVE_MAP_CHANGE | MOVE_END_TURN);
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::avatarMovedInDungeon(MoveEvent &event) {
|
||||
Direction realDir = dirNormalize((Direction)g_ultima->_saveGame->_orientation, event._dir);
|
||||
Dungeon *dungeon = dynamic_cast<Dungeon *>(g_context->_location->_map);
|
||||
assert(dungeon);
|
||||
|
||||
if (!settings._filterMoveMessages) {
|
||||
if (event._userEvent) {
|
||||
if (event._result & MOVE_TURNED) {
|
||||
if (dirRotateCCW((Direction)g_ultima->_saveGame->_orientation) == realDir)
|
||||
g_screen->screenMessage("Turn Left\n");
|
||||
else
|
||||
g_screen->screenMessage("Turn Right\n");
|
||||
} else {
|
||||
// Show 'Advance' or 'Retreat' in dungeons
|
||||
g_screen->screenMessage("%s\n", realDir == g_ultima->_saveGame->_orientation ? "Advance" : "Retreat");
|
||||
}
|
||||
}
|
||||
|
||||
if (event._result & MOVE_BLOCKED)
|
||||
g_screen->screenMessage("%cBlocked!%c\n", FG_GREY, FG_WHITE);
|
||||
}
|
||||
|
||||
// If we're exiting the map, do this
|
||||
if (event._result & MOVE_EXIT_TO_PARENT) {
|
||||
g_screen->screenMessage("%cLeaving...%c\n", FG_GREY, FG_WHITE);
|
||||
exitToParentMap();
|
||||
g_music->playMapMusic();
|
||||
}
|
||||
|
||||
// Check to see if we're entering a dungeon room
|
||||
if (event._result & MOVE_SUCCEEDED) {
|
||||
if (dungeon->currentToken() == DUNGEON_ROOM) {
|
||||
int room = (int)dungeon->currentSubToken(); // Get room number
|
||||
|
||||
/**
|
||||
* recalculate room for the abyss -- there are 16 rooms for every 2 levels,
|
||||
* each room marked with 0xD* where (* == room number 0-15).
|
||||
* for levels 1 and 2, there are 16 rooms, levels 3 and 4 there are 16 rooms, etc.
|
||||
*/
|
||||
if (g_context->_location->_map->_id == MAP_ABYSS)
|
||||
room = (0x10 * (g_context->_location->_coords.z / 2)) + room;
|
||||
|
||||
Dungeon *dng = dynamic_cast<Dungeon *>(g_context->_location->_map);
|
||||
assert(dng);
|
||||
dng->_currentRoom = room;
|
||||
|
||||
// Set the map and start combat!
|
||||
CombatController *cc = new CombatController(dng->_roomMaps[room]);
|
||||
cc->initDungeonRoom(room, dirReverse(realDir));
|
||||
cc->begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::timerFired() {
|
||||
if (_pausedTimer > 0) {
|
||||
_pausedTimer--;
|
||||
if (_pausedTimer <= 0) {
|
||||
_pausedTimer = 0;
|
||||
_paused = false; /* unpause the game */
|
||||
}
|
||||
}
|
||||
|
||||
if (!_paused && !_pausedTimer) {
|
||||
if (++g_context->_windCounter >= MOON_SECONDS_PER_PHASE * 4) {
|
||||
if (xu4_random(4) == 1 && !g_context->_windLock)
|
||||
g_context->_windDirection = dirRandomDir(MASK_DIR_ALL);
|
||||
g_context->_windCounter = 0;
|
||||
}
|
||||
|
||||
/* balloon moves about 4 times per second */
|
||||
if ((g_context->_transportContext == TRANSPORT_BALLOON) &&
|
||||
g_context->_party->isFlying()) {
|
||||
g_context->_location->move(dirReverse((Direction) g_context->_windDirection), false);
|
||||
}
|
||||
|
||||
updateMoons(true);
|
||||
|
||||
g_screen->screenCycle();
|
||||
|
||||
// Check for any right-button mouse movement
|
||||
KeybindingAction action = eventHandler->getAction();
|
||||
if (action != KEYBIND_NONE)
|
||||
keybinder(action);
|
||||
|
||||
// Do game udpates to the screen, like tile animations
|
||||
gameUpdateScreen();
|
||||
|
||||
/*
|
||||
* force pass if no commands within last 20 seconds
|
||||
*/
|
||||
Controller *controller = eventHandler->getController();
|
||||
if (controller != nullptr && (eventHandler->getController() == g_game ||
|
||||
dynamic_cast<CombatController *>(eventHandler->getController()) != nullptr) &&
|
||||
gameTimeSinceLastCommand() > 20) {
|
||||
|
||||
/* pass the turn, and redraw the text area so the prompt is shown */
|
||||
MetaEngine::executeAction(KEYBIND_PASS);
|
||||
g_screen->screenRedrawTextArea(TEXT_AREA_X, TEXT_AREA_Y, TEXT_AREA_W, TEXT_AREA_H);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GameController::checkSpecialCreatures(Direction dir) {
|
||||
int i;
|
||||
Object *obj;
|
||||
static const struct {
|
||||
int x, y;
|
||||
Direction dir;
|
||||
} pirateInfo[] = {
|
||||
{ 224, 220, DIR_EAST }, /* N'M" O'A" */
|
||||
{ 224, 228, DIR_EAST }, /* O'E" O'A" */
|
||||
{ 226, 220, DIR_EAST }, /* O'E" O'C" */
|
||||
{ 227, 228, DIR_EAST }, /* O'E" O'D" */
|
||||
{ 228, 227, DIR_SOUTH }, /* O'D" O'E" */
|
||||
{ 229, 225, DIR_SOUTH }, /* O'B" O'F" */
|
||||
{ 229, 223, DIR_NORTH }, /* N'P" O'F" */
|
||||
{ 228, 222, DIR_NORTH } /* N'O" O'E" */
|
||||
};
|
||||
|
||||
/*
|
||||
* if heading east into pirates cove (O'A" N'N"), generate pirate
|
||||
* ships
|
||||
*/
|
||||
if (dir == DIR_EAST &&
|
||||
g_context->_location->_coords.x == 0xdd &&
|
||||
g_context->_location->_coords.y == 0xe0) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
obj = g_context->_location->_map->addCreature(creatureMgr->getById(PIRATE_ID), MapCoords(pirateInfo[i].x, pirateInfo[i].y));
|
||||
obj->setDirection(pirateInfo[i].dir);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if heading south towards the shrine of humility, generate
|
||||
* daemons unless horn has been blown
|
||||
*/
|
||||
if (dir == DIR_SOUTH &&
|
||||
g_context->_location->_coords.x >= 229 &&
|
||||
g_context->_location->_coords.x < 234 &&
|
||||
g_context->_location->_coords.y >= 212 &&
|
||||
g_context->_location->_coords.y < 217 &&
|
||||
*g_context->_aura != Aura::HORN) {
|
||||
for (i = 0; i < 8; i++)
|
||||
g_context->_location->_map->addCreature(creatureMgr->getById(DAEMON_ID), MapCoords(231, g_context->_location->_coords.y + 1, g_context->_location->_coords.z));
|
||||
}
|
||||
}
|
||||
|
||||
bool GameController::checkMoongates() {
|
||||
Coords dest;
|
||||
|
||||
if (g_moongates->findActiveGateAt(g_ultima->_saveGame->_trammelPhase, g_ultima->_saveGame->_feluccaPhase, g_context->_location->_coords, dest)) {
|
||||
|
||||
gameSpellEffect(-1, -1, SOUND_MOONGATE); // Default spell effect (screen inversion without 'spell' sound effects)
|
||||
|
||||
if (g_context->_location->_coords != dest) {
|
||||
g_context->_location->_coords = dest;
|
||||
gameSpellEffect(-1, -1, SOUND_MOONGATE); // Again, after arriving
|
||||
}
|
||||
|
||||
if (g_moongates->isEntryToShrineOfSpirituality(g_ultima->_saveGame->_trammelPhase, g_ultima->_saveGame->_feluccaPhase)) {
|
||||
Shrine *shrine_spirituality;
|
||||
|
||||
shrine_spirituality = dynamic_cast<Shrine *>(mapMgr->get(MAP_SHRINE_SPIRITUALITY));
|
||||
assert(shrine_spirituality);
|
||||
|
||||
if (!g_context->_party->canEnterShrine(VIRT_SPIRITUALITY))
|
||||
return true;
|
||||
|
||||
setMap(shrine_spirituality, 1, nullptr);
|
||||
g_music->playMapMusic();
|
||||
|
||||
shrine_spirituality->enter();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GameController::creatureCleanup() {
|
||||
ObjectDeque::iterator i;
|
||||
Map *map = g_context->_location->_map;
|
||||
|
||||
for (i = map->_objects.begin(); i != map->_objects.end();) {
|
||||
Object *obj = *i;
|
||||
MapCoords o_coords = obj->getCoords();
|
||||
|
||||
if ((obj->getType() == Object::CREATURE) && (o_coords.z == g_context->_location->_coords.z) &&
|
||||
o_coords.distance(g_context->_location->_coords, g_context->_location->_map) > MAX_CREATURE_DISTANCE) {
|
||||
|
||||
/* delete the object and remove it from the map */
|
||||
i = map->removeObject(i);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::checkRandomCreatures() {
|
||||
int canSpawnHere = g_context->_location->_map->isWorldMap() || g_context->_location->_context & CTX_DUNGEON;
|
||||
#ifdef IOS_ULTIMA4
|
||||
int spawnDivisor = c->location->context & CTX_DUNGEON ? (53 - (c->location->coords.z << 2)) : 53;
|
||||
#else
|
||||
int spawnDivisor = g_context->_location->_context & CTX_DUNGEON ? (32 - (g_context->_location->_coords.z << 2)) : 32;
|
||||
#endif
|
||||
|
||||
/* If there are too many creatures already,
|
||||
or we're not on the world map, don't worry about it! */
|
||||
if (!canSpawnHere ||
|
||||
g_context->_location->_map->getNumberOfCreatures() >= MAX_CREATURES_ON_MAP ||
|
||||
xu4_random(spawnDivisor) != 0)
|
||||
return;
|
||||
|
||||
// If combat is turned off, then don't spawn any creator
|
||||
if (g_debugger->_disableCombat)
|
||||
return;
|
||||
|
||||
gameSpawnCreature(nullptr);
|
||||
}
|
||||
|
||||
void GameController::checkBridgeTrolls() {
|
||||
const Tile *bridge = g_context->_location->_map->_tileSet->getByName("bridge");
|
||||
if (!bridge)
|
||||
return;
|
||||
|
||||
// TODO: CHEST: Make a user option to not make chests block bridge trolls
|
||||
if (!g_context->_location->_map->isWorldMap() ||
|
||||
g_context->_location->_map->tileAt(g_context->_location->_coords, WITH_OBJECTS)->_id != bridge->getId() ||
|
||||
xu4_random(8) != 0)
|
||||
return;
|
||||
|
||||
g_screen->screenMessage("\nBridge Trolls!\n");
|
||||
|
||||
Creature *m = g_context->_location->_map->addCreature(creatureMgr->getById(TROLL_ID), g_context->_location->_coords);
|
||||
CombatController *cc = new CombatController(MAP_BRIDGE_CON);
|
||||
cc->init(m);
|
||||
cc->begin();
|
||||
}
|
||||
|
||||
bool GameController::createBalloon(Map *map) {
|
||||
ObjectDeque::iterator i;
|
||||
|
||||
/* see if the balloon has already been created (and not destroyed) */
|
||||
for (auto *obj : map->_objects) {
|
||||
if (obj->getTile().getTileType()->isBalloon())
|
||||
return false;
|
||||
}
|
||||
|
||||
const Tile *balloon = map->_tileSet->getByName("balloon");
|
||||
assertMsg(balloon, "no balloon tile found in tileset");
|
||||
map->addObject(balloon->getId(), balloon->getId(), map->getLabel("balloon"));
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameController::attack(Direction dir) {
|
||||
g_screen->screenMessage("Attack: ");
|
||||
if (g_context->_party->isFlying()) {
|
||||
g_screen->screenMessage("\n%cDrift only!%c\n", FG_GREY, FG_WHITE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dir == DIR_NONE)
|
||||
dir = gameGetDirection();
|
||||
|
||||
if (dir == DIR_NONE) {
|
||||
g_screen->screenMessage("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Std::vector<Coords> path = gameGetDirectionalActionPath(
|
||||
MASK_DIR(dir), MASK_DIR_ALL, g_context->_location->_coords,
|
||||
1, 1, nullptr, true);
|
||||
for (const auto &coords : path) {
|
||||
if (attackAt(coords))
|
||||
return;
|
||||
}
|
||||
|
||||
g_screen->screenMessage("%cNothing to Attack!%c\n", FG_GREY, FG_WHITE);
|
||||
}
|
||||
|
||||
bool GameController::attackAt(const Coords &coords) {
|
||||
Object *under;
|
||||
const Tile *ground;
|
||||
Creature *m;
|
||||
|
||||
m = dynamic_cast<Creature *>(g_context->_location->_map->objectAt(coords));
|
||||
// Nothing attackable: move on to next tile
|
||||
if (m == nullptr || !m->isAttackable())
|
||||
return false;
|
||||
|
||||
// Attack successful
|
||||
/// TODO: CHEST: Make a user option to not make chests change battlefield
|
||||
/// map (1 of 2)
|
||||
ground = g_context->_location->_map->tileTypeAt(g_context->_location->_coords, WITH_GROUND_OBJECTS);
|
||||
if (!ground->isChest()) {
|
||||
ground = g_context->_location->_map->tileTypeAt(g_context->_location->_coords, WITHOUT_OBJECTS);
|
||||
if ((under = g_context->_location->_map->objectAt(g_context->_location->_coords)) &&
|
||||
under->getTile().getTileType()->isShip())
|
||||
ground = under->getTile().getTileType();
|
||||
}
|
||||
|
||||
// You're attacking a townsperson! Alert the guards!
|
||||
if ((m->getType() == Object::PERSON) && (m->getMovementBehavior() != MOVEMENT_ATTACK_AVATAR))
|
||||
g_context->_location->_map->alertGuards();
|
||||
|
||||
// Not good karma to be killing the innocent. Bad avatar!
|
||||
if (m->isGood() || /* attacking a good creature */
|
||||
/* attacking a docile (although possibly evil) person in town */
|
||||
((m->getType() == Object::PERSON) && (m->getMovementBehavior() != MOVEMENT_ATTACK_AVATAR)))
|
||||
g_context->_party->adjustKarma(KA_ATTACKED_GOOD);
|
||||
|
||||
CombatController *cc = new CombatController(CombatMap::mapForTile(ground, g_context->_party->getTransport().getTileType(), m));
|
||||
cc->init(m);
|
||||
cc->begin();
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
195
engines/ultima/ultima4/controllers/game_controller.h
Normal file
195
engines/ultima/ultima4/controllers/game_controller.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_GAME_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_GAME_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/controller.h"
|
||||
#include "ultima/ultima4/core/coords.h"
|
||||
#include "ultima/ultima4/core/observer.h"
|
||||
#include "ultima/ultima4/game/portal.h"
|
||||
#include "ultima/ultima4/game/player.h"
|
||||
#include "ultima/ultima4/map/location.h"
|
||||
#include "ultima/ultima4/views/tileview.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
/**
|
||||
* The main game controller that handles basic game flow and keypresses.
|
||||
*
|
||||
* @todo
|
||||
* <ul>
|
||||
* <li>separate the dungeon specific stuff into another class (subclass?)</li>
|
||||
* </ul>
|
||||
*/
|
||||
class GameController : public Controller, public Observer<Party *, PartyEvent &>, public Observer<Location *, MoveEvent &>,
|
||||
public TurnCompleter {
|
||||
private:
|
||||
/**
|
||||
* Handles feedback after avatar moved during normal 3rd-person view.
|
||||
*/
|
||||
void avatarMoved(MoveEvent &event);
|
||||
|
||||
/**
|
||||
* Handles feedback after moving the avatar in the 3-d dungeon view.
|
||||
*/
|
||||
void avatarMovedInDungeon(MoveEvent &event);
|
||||
|
||||
/**
|
||||
* Removes creatures from the current map if they are too far away from the avatar
|
||||
*/
|
||||
void creatureCleanup();
|
||||
|
||||
/**
|
||||
* Handles trolls under bridges
|
||||
*/
|
||||
void checkBridgeTrolls();
|
||||
|
||||
/**
|
||||
* Checks creature conditions and spawns new creatures if necessary
|
||||
*/
|
||||
void checkRandomCreatures();
|
||||
|
||||
/**
|
||||
* Checks for valid conditions and handles
|
||||
* special creatures guarding the entrance to the
|
||||
* abyss and to the shrine of spirituality
|
||||
*/
|
||||
void checkSpecialCreatures(Direction dir);
|
||||
|
||||
/**
|
||||
* Checks for and handles when the avatar steps on a moongate
|
||||
*/
|
||||
bool checkMoongates();
|
||||
|
||||
/**
|
||||
* Creates the balloon near Hythloth, but only if the balloon doesn't already exists somewhere
|
||||
*/
|
||||
bool createBalloon(Map *map);
|
||||
|
||||
/**
|
||||
* Attempts to attack a creature at map coordinates x,y. If no
|
||||
* creature is present at that point, zero is returned.
|
||||
*/
|
||||
bool attackAt(const Coords &coords);
|
||||
public:
|
||||
/**
|
||||
* Show an attack flash at x, y on the current map.
|
||||
* This is used for 'being hit' or 'being missed'
|
||||
* by weapons, cannon fire, spells, etc.
|
||||
*/
|
||||
static void flashTile(const Coords &coords, MapTile tile, int timeFactor);
|
||||
|
||||
static void flashTile(const Coords &coords, const Common::String &tilename, int timeFactor);
|
||||
static void doScreenAnimationsWhilePausing(int timeFactor);
|
||||
public:
|
||||
TileView _mapArea;
|
||||
bool _paused;
|
||||
int _pausedTimer;
|
||||
bool _combatFinished;
|
||||
public:
|
||||
GameController();
|
||||
|
||||
/* controller functions */
|
||||
|
||||
/**
|
||||
* Called when a controller is made active
|
||||
*/
|
||||
void setActive() override;
|
||||
|
||||
/**
|
||||
* Keybinder actions
|
||||
*/
|
||||
void keybinder(KeybindingAction action) override;
|
||||
|
||||
/**
|
||||
* Mouse button was pressed
|
||||
*/
|
||||
bool mousePressed(const Common::Point &mousePos) override;
|
||||
|
||||
/**
|
||||
* This function is called every quarter second.
|
||||
*/
|
||||
void timerFired() override;
|
||||
|
||||
/* main game functions */
|
||||
void init();
|
||||
void initScreen();
|
||||
void initScreenWithoutReloadingState();
|
||||
void setMap(Map *map, bool saveLocation, const Portal *portal, TurnCompleter *turnCompleter = nullptr);
|
||||
|
||||
/**
|
||||
* Exits the current map and location and returns to its parent location
|
||||
* This restores all relevant information from the previous location,
|
||||
* such as the map, map position, etc. (such as exiting a city)
|
||||
**/
|
||||
int exitToParentMap();
|
||||
|
||||
/**
|
||||
* Finishes the game turn after combat ends. It suppresses monster
|
||||
* movement to prevent issues, such as infinite combat at the
|
||||
* Shrine of Humility
|
||||
*/
|
||||
void finishTurnAfterCombatEnds() override {
|
||||
_combatFinished = true;
|
||||
finishTurn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates a game turn. This performs the post-turn housekeeping
|
||||
* tasks like adjusting the party's food, incrementing the number of
|
||||
* moves, etc.
|
||||
*/
|
||||
void finishTurn() override;
|
||||
|
||||
/**
|
||||
* Provide feedback to user after a party event happens.
|
||||
*/
|
||||
void update(Party *party, PartyEvent &event) override;
|
||||
|
||||
/**
|
||||
* Provide feedback to user after a movement event happens.
|
||||
*/
|
||||
void update(Location *location, MoveEvent &event) override;
|
||||
|
||||
/**
|
||||
* Initializes the moon state according to the savegame file. This method of
|
||||
* initializing the moons (rather than just setting them directly) is necessary
|
||||
* to make sure trammel and felucca stay in sync
|
||||
*/
|
||||
void initMoons();
|
||||
|
||||
/**
|
||||
* Updates the phases of the moons and shows
|
||||
* the visual moongates on the map, if desired
|
||||
*/
|
||||
void updateMoons(bool showmoongates);
|
||||
|
||||
void attack(Direction dir = DIR_NONE);
|
||||
};
|
||||
|
||||
extern GameController *g_game;
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
175
engines/ultima/ultima4/controllers/inn_controller.cpp
Normal file
175
engines/ultima/ultima4/controllers/inn_controller.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/* 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 "ultima/ultima4/controllers/inn_controller.h"
|
||||
#include "ultima/ultima4/conversation/conversation.h"
|
||||
#include "ultima/ultima4/core/utils.h"
|
||||
#include "ultima/ultima4/map/city.h"
|
||||
#include "ultima/ultima4/map/mapmgr.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
InnController::InnController() {
|
||||
_map = nullptr;
|
||||
/*
|
||||
* Normally in cities, only one opponent per encounter; inn's
|
||||
* override this to get the regular encounter size.
|
||||
*/
|
||||
_forceStandardEncounterSize = true;
|
||||
}
|
||||
|
||||
void InnController::begin() {
|
||||
/* first, show the avatar before sleeping */
|
||||
gameUpdateScreen();
|
||||
|
||||
/* in the original, the vendor music plays straight through sleeping */
|
||||
if (settings._enhancements)
|
||||
g_music->fadeOut(INN_FADE_OUT_TIME); /* Fade volume out to ease into rest */
|
||||
|
||||
EventHandler::wait_msecs(INN_FADE_OUT_TIME);
|
||||
|
||||
/* show the sleeping avatar */
|
||||
g_context->_party->setTransport(g_context->_location->_map->_tileSet->getByName("corpse")->getId());
|
||||
gameUpdateScreen();
|
||||
|
||||
g_screen->screenDisableCursor();
|
||||
|
||||
EventHandler::wait_msecs(settings._innTime * 1000);
|
||||
|
||||
g_screen->screenEnableCursor();
|
||||
|
||||
/* restore the avatar to normal */
|
||||
g_context->_party->setTransport(g_context->_location->_map->_tileSet->getByName("avatar")->getId());
|
||||
gameUpdateScreen();
|
||||
|
||||
/* the party is always healed */
|
||||
heal();
|
||||
|
||||
/* Is there a special encounter during your stay? */
|
||||
// mwinterrowd suggested code, based on u4dos
|
||||
if (g_context->_party->member(0)->isDead()) {
|
||||
maybeMeetIsaac();
|
||||
} else {
|
||||
if (xu4_random(8) != 0) {
|
||||
maybeMeetIsaac();
|
||||
} else {
|
||||
maybeAmbush();
|
||||
}
|
||||
}
|
||||
|
||||
g_screen->screenMessage("\nMorning!\n");
|
||||
g_screen->screenPrompt();
|
||||
|
||||
g_music->fadeIn(INN_FADE_IN_TIME, true);
|
||||
}
|
||||
|
||||
bool InnController::heal() {
|
||||
// restore each party member to max mp, and restore some hp
|
||||
bool healed = false;
|
||||
for (int i = 0; i < g_context->_party->size(); i++) {
|
||||
PartyMember *m = g_context->_party->member(i);
|
||||
m->setMp(m->getMaxMp());
|
||||
if ((m->getHp() < m->getMaxHp()) && m->heal(HT_INNHEAL))
|
||||
healed = true;
|
||||
}
|
||||
|
||||
return healed;
|
||||
}
|
||||
|
||||
|
||||
void InnController::maybeMeetIsaac() {
|
||||
// Does Isaac the Ghost pay a visit to the Avatar?
|
||||
// if ((location == skara_brae) && (random(4) = 0) {
|
||||
// // create Isaac the Ghost
|
||||
// }
|
||||
if ((g_context->_location->_map->_id == 11) && (xu4_random(4) == 0)) {
|
||||
City *city = dynamic_cast<City *>(g_context->_location->_map);
|
||||
assert(city);
|
||||
|
||||
if (city->_extraDialogues.size() == 1 &&
|
||||
city->_extraDialogues[0]->getName() == "Isaac") {
|
||||
|
||||
Coords coords(27, xu4_random(3) + 10, g_context->_location->_coords.z);
|
||||
|
||||
// If Isaac is already around, just bring him back to the inn
|
||||
for (ObjectDeque::iterator i = g_context->_location->_map->_objects.begin();
|
||||
i != g_context->_location->_map->_objects.end();
|
||||
i++) {
|
||||
Person *p = dynamic_cast<Person *>(*i);
|
||||
if (p && p->getName() == "Isaac") {
|
||||
p->setCoords(coords);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we need to create Isaac
|
||||
Person *isaac = new Person(creatureMgr->getById(GHOST_ID)->getTile());
|
||||
|
||||
isaac->setMovementBehavior(MOVEMENT_WANDER);
|
||||
|
||||
isaac->setDialogue(city->_extraDialogues[0]);
|
||||
isaac->getStart() = coords;
|
||||
isaac->setPrevTile(isaac->getTile());
|
||||
|
||||
// Add Isaac near the Avatar
|
||||
city->addPerson(isaac);
|
||||
|
||||
delete isaac;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InnController::maybeAmbush() {
|
||||
if (settings._innAlwaysCombat || (xu4_random(8) == 0)) {
|
||||
MapId mapid;
|
||||
Creature *creature;
|
||||
bool showMessage = true;
|
||||
|
||||
/* Rats seem much more rare than meeting rogues in the streets */
|
||||
if (xu4_random(4) == 0) {
|
||||
/* Rats! */
|
||||
mapid = MAP_BRICK_CON;
|
||||
creature = g_context->_location->_map->addCreature(creatureMgr->getById(RAT_ID), g_context->_location->_coords);
|
||||
} else {
|
||||
/* While strolling down the street, attacked by rogues! */
|
||||
mapid = MAP_INN_CON;
|
||||
creature = g_context->_location->_map->addCreature(creatureMgr->getById(ROGUE_ID), g_context->_location->_coords);
|
||||
g_screen->screenMessage("\nIn the middle of the night while out on a stroll...\n\n");
|
||||
showMessage = false;
|
||||
}
|
||||
|
||||
|
||||
_map = getCombatMap(mapMgr->get(mapid));
|
||||
g_game->setMap(_map, true, nullptr, this);
|
||||
|
||||
init(creature);
|
||||
showCombatMessage(showMessage);
|
||||
CombatController::begin();
|
||||
}
|
||||
}
|
||||
|
||||
void InnController::awardLoot() {
|
||||
// never get a chest from inn combat
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
46
engines/ultima/ultima4/controllers/inn_controller.h
Normal file
46
engines/ultima/ultima4/controllers/inn_controller.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_INN_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_INN_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/combat_controller.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
class InnController : public CombatController {
|
||||
public:
|
||||
InnController();
|
||||
|
||||
void begin() override;
|
||||
void awardLoot() override;
|
||||
|
||||
private:
|
||||
bool heal();
|
||||
void maybeMeetIsaac();
|
||||
void maybeAmbush();
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
1942
engines/ultima/ultima4/controllers/intro_controller.cpp
Normal file
1942
engines/ultima/ultima4/controllers/intro_controller.cpp
Normal file
File diff suppressed because it is too large
Load Diff
436
engines/ultima/ultima4/controllers/intro_controller.h
Normal file
436
engines/ultima/ultima4/controllers/intro_controller.h
Normal file
@@ -0,0 +1,436 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_INTRO_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_INTRO_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/controller.h"
|
||||
#include "ultima/ultima4/core/observer.h"
|
||||
#include "ultima/ultima4/filesys/savegame.h"
|
||||
#include "ultima/ultima4/views/menu.h"
|
||||
#include "ultima/ultima4/views/textview.h"
|
||||
#include "ultima/ultima4/views/imageview.h"
|
||||
#include "ultima/ultima4/views/tileview.h"
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
class IntroObjectState;
|
||||
class Tile;
|
||||
|
||||
/**
|
||||
* Binary data loaded from the U4DOS title.exe file.
|
||||
*/
|
||||
class IntroBinData {
|
||||
private:
|
||||
// disallow assignments, copy construction
|
||||
IntroBinData(const IntroBinData &);
|
||||
const IntroBinData &operator=(const IntroBinData &);
|
||||
void openFile(Common::File &f, const Common::String &name);
|
||||
public:
|
||||
IntroBinData();
|
||||
~IntroBinData();
|
||||
|
||||
bool load();
|
||||
|
||||
Std::vector<MapTile> _introMap;
|
||||
byte *_sigData;
|
||||
byte *_scriptTable;
|
||||
Tile **_baseTileTable;
|
||||
byte *_beastie1FrameTable;
|
||||
byte *_beastie2FrameTable;
|
||||
Std::vector<Common::String> _introText;
|
||||
Std::vector<Common::String> _introQuestions;
|
||||
Std::vector<Common::String> _introGypsy;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Controls the title animation sequences, including the traditional
|
||||
* plotted "Lord British" signature, the pixelized fade-in of the
|
||||
* "Ultima IV" game title, as well as the other more simple animated
|
||||
* features, followed by the traditional animated map and "Journey
|
||||
* Onward" menu, plus the xU4-specific configuration menu.
|
||||
*
|
||||
* @todo
|
||||
* <ul>
|
||||
* <li>make initial menu a Menu too</li>
|
||||
* <li>get rid of mode and switch(mode) statements</li>
|
||||
* <li>get rid global intro instance -- should only need to be accessed from u4.cpp</li>
|
||||
* </ul>
|
||||
*/
|
||||
class IntroController : public Controller, public Observer<Menu *, MenuEvent &> {
|
||||
public:
|
||||
IntroController();
|
||||
~IntroController() override;
|
||||
|
||||
/**
|
||||
* Initializes intro state and loads in introduction graphics, text
|
||||
* and map data from title.exe.
|
||||
*/
|
||||
bool init();
|
||||
bool hasInitiatedNewGame();
|
||||
|
||||
/**
|
||||
* Frees up data not needed after introduction.
|
||||
*/
|
||||
void deleteIntro();
|
||||
|
||||
/**
|
||||
* Handles keystrokes during the introduction.
|
||||
*/
|
||||
bool keyPressed(int key) override;
|
||||
|
||||
/**
|
||||
* Mouse button was pressed
|
||||
*/
|
||||
bool mousePressed(const Common::Point &mousePos) override;
|
||||
|
||||
byte *getSigData();
|
||||
|
||||
/**
|
||||
* Paints the screen.
|
||||
*/
|
||||
void updateScreen();
|
||||
|
||||
/**
|
||||
* Timer callback for the intro sequence. Handles animating the intro
|
||||
* map, the beasties, etc..
|
||||
*/
|
||||
void timerFired() override;
|
||||
|
||||
/**
|
||||
* Preload map tiles
|
||||
*/
|
||||
void preloadMap();
|
||||
|
||||
/**
|
||||
* Update the screen when an observed menu is reset or has an item
|
||||
* activated.
|
||||
* TODO: Reduce duped code.
|
||||
*/
|
||||
void update(Menu *menu, MenuEvent &event) override;
|
||||
void updateConfMenu(MenuEvent &event);
|
||||
void updateVideoMenu(MenuEvent &event);
|
||||
void updateGfxMenu(MenuEvent &event);
|
||||
void updateSoundMenu(MenuEvent &event);
|
||||
void updateInputMenu(MenuEvent &event);
|
||||
void updateSpeedMenu(MenuEvent &event);
|
||||
void updateGameplayMenu(MenuEvent &event);
|
||||
void updateInterfaceMenu(MenuEvent &event);
|
||||
|
||||
//
|
||||
// Title methods
|
||||
//
|
||||
/**
|
||||
* Initialize the title elements
|
||||
*/
|
||||
void initTitles();
|
||||
|
||||
/**
|
||||
* Update the title element, drawing the appropriate frame of animation
|
||||
*/
|
||||
bool updateTitle();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Draws the small map on the intro screen.
|
||||
*/
|
||||
void drawMap();
|
||||
void drawMapStatic();
|
||||
void drawMapAnimated();
|
||||
|
||||
/**
|
||||
* Draws the animated beasts in the upper corners of the screen.
|
||||
*/
|
||||
void drawBeasties();
|
||||
|
||||
/**
|
||||
* Animates the "beasties". The animate intro image is made up frames
|
||||
* for the two creatures in the top left and top right corners of the
|
||||
* screen. This function draws the frame for the given beastie on the
|
||||
* screen. vertoffset is used lower the creatures down from the top
|
||||
* of the screen.
|
||||
*/
|
||||
void drawBeastie(int beast, int vertoffset, int frame);
|
||||
|
||||
/**
|
||||
* Animates the moongate in the tree intro image. There are two
|
||||
* overlays in the part of the image normally covered by the text. If
|
||||
* the frame parameter is "moongate", the moongate overlay is painted
|
||||
* over the image. If frame is "items", the second overlay is
|
||||
* painted: the circle without the moongate, but with a small white
|
||||
* dot representing the anhk and history book.
|
||||
*/
|
||||
void animateTree(const Common::String &frame);
|
||||
|
||||
/**
|
||||
* Draws the cards in the character creation sequence with the gypsy.
|
||||
*/
|
||||
void drawCard(int pos, int card);
|
||||
|
||||
/**
|
||||
* Draws the beads in the abacus during the character creation sequence
|
||||
*/
|
||||
void drawAbacusBeads(int row, int selectedVirtue, int rejectedVirtue);
|
||||
|
||||
/**
|
||||
* Initializes the question tree. The tree starts off with the first
|
||||
* eight entries set to the numbers 0-7 in a random order.
|
||||
*/
|
||||
void initQuestionTree();
|
||||
|
||||
/**
|
||||
* Updates the question tree with the given answer, and advances to
|
||||
* the next round.
|
||||
* @return true if all questions have been answered, false otherwise
|
||||
*/
|
||||
bool doQuestion(int answer);
|
||||
|
||||
/**
|
||||
* Build the initial avatar player record from the answers to the
|
||||
* gypsy's questions.
|
||||
*/
|
||||
void initPlayers(SaveGame *saveGame);
|
||||
|
||||
/**
|
||||
* Get the text for the question giving a choice between virtue v1 and
|
||||
* virtue v2 (zero based virtue index, starting at honesty).
|
||||
*/
|
||||
Common::String getQuestion(int v1, int v2);
|
||||
#ifdef IOS_ULTIMA4
|
||||
public:
|
||||
/**
|
||||
* Try to put the intro music back at just the correct moment on iOS;
|
||||
* don't play it at the very beginning.
|
||||
*/
|
||||
void tryTriggerIntroMusic();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initiate a new savegame by reading the name, sex, then presenting a
|
||||
* series of questions to determine the class of the new character.
|
||||
*/
|
||||
void initiateNewGame();
|
||||
void finishInitiateGame(const Common::String &nameBuffer, SexType sex);
|
||||
|
||||
/**
|
||||
* Starts the gypsys questioning that eventually determines the new
|
||||
* characters class.
|
||||
*/
|
||||
void startQuestions();
|
||||
void showStory();
|
||||
|
||||
/**
|
||||
* Starts the game.
|
||||
*/
|
||||
void journeyOnward();
|
||||
|
||||
/**
|
||||
* Shows an about box.
|
||||
*/
|
||||
void about();
|
||||
#ifdef IOS_ULTIMA4
|
||||
private:
|
||||
#endif
|
||||
/**
|
||||
* Shows text in the question area.
|
||||
*/
|
||||
void showText(const Common::String &text);
|
||||
|
||||
/**
|
||||
* Run a menu and return when the menu has been closed. Screen
|
||||
* updates are handled by observing the menu.
|
||||
*/
|
||||
void runMenu(Menu *menu, TextView *view, bool withBeasties);
|
||||
|
||||
/**
|
||||
* The states of the intro.
|
||||
*/
|
||||
enum {
|
||||
INTRO_TITLES, // displaying the animated intro titles
|
||||
INTRO_MAP, // displaying the animated intro map
|
||||
INTRO_MENU, // displaying the main menu: journey onward, etc.
|
||||
INTRO_ABOUT
|
||||
} _mode;
|
||||
|
||||
enum MenuConstants {
|
||||
MI_CONF_VIDEO,
|
||||
MI_CONF_SOUND,
|
||||
MI_CONF_INPUT,
|
||||
MI_CONF_SPEED,
|
||||
MI_CONF_GAMEPLAY,
|
||||
MI_CONF_INTERFACE,
|
||||
MI_CONF_01,
|
||||
MI_VIDEO_CONF_GFX,
|
||||
MI_VIDEO_02,
|
||||
MI_VIDEO_03,
|
||||
MI_VIDEO_07,
|
||||
MI_VIDEO_08,
|
||||
MI_GFX_SCHEME,
|
||||
MI_GFX_TILE_TRANSPARENCY,
|
||||
MI_GFX_TILE_TRANSPARENCY_SHADOW_SIZE,
|
||||
MI_GFX_TILE_TRANSPARENCY_SHADOW_OPACITY,
|
||||
MI_GFX_RETURN,
|
||||
MI_SOUND_03,
|
||||
MI_INPUT_03,
|
||||
MI_SPEED_01,
|
||||
MI_SPEED_02,
|
||||
MI_SPEED_03,
|
||||
MI_SPEED_04,
|
||||
MI_SPEED_05,
|
||||
MI_SPEED_06,
|
||||
MI_SPEED_07,
|
||||
MI_GAMEPLAY_01,
|
||||
MI_GAMEPLAY_02,
|
||||
MI_GAMEPLAY_03,
|
||||
MI_GAMEPLAY_04,
|
||||
MI_GAMEPLAY_05,
|
||||
MI_GAMEPLAY_06,
|
||||
MI_INTERFACE_01,
|
||||
MI_INTERFACE_02,
|
||||
MI_INTERFACE_03,
|
||||
MI_INTERFACE_04,
|
||||
MI_INTERFACE_05,
|
||||
MI_INTERFACE_06,
|
||||
USE_SETTINGS = 0xFE,
|
||||
CANCEL = 0xFF
|
||||
};
|
||||
|
||||
ImageView _backgroundArea;
|
||||
TextView _menuArea;
|
||||
TextView _extendedMenuArea;
|
||||
TextView _questionArea;
|
||||
TileView _mapArea;
|
||||
Image *_mapScreen;
|
||||
|
||||
// menus
|
||||
Menu _mainMenu;
|
||||
Menu _confMenu;
|
||||
Menu _videoMenu;
|
||||
Menu _gfxMenu;
|
||||
Menu _soundMenu;
|
||||
Menu _inputMenu;
|
||||
Menu _speedMenu;
|
||||
Menu _gameplayMenu;
|
||||
Menu _interfaceMenu;
|
||||
|
||||
// data loaded in from title.exe
|
||||
IntroBinData *_binData;
|
||||
|
||||
// additional introduction state data
|
||||
Common::String _errorMessage;
|
||||
int _answerInd;
|
||||
int _questionRound;
|
||||
int _questionTree[15];
|
||||
int _beastie1Cycle;
|
||||
int _beastie2Cycle;
|
||||
int _beastieOffset;
|
||||
bool _beastiesVisible;
|
||||
int _sleepCycles;
|
||||
int _scrPos; /* current position in the script table */
|
||||
IntroObjectState *_objectStateTable;
|
||||
|
||||
bool _justInitiatedNewGame;
|
||||
Common::String _profileName;
|
||||
bool _useProfile;
|
||||
|
||||
//
|
||||
// Title defs, structs, methods, and data members
|
||||
//
|
||||
enum AnimType {
|
||||
SIGNATURE,
|
||||
AND,
|
||||
BAR,
|
||||
ORIGIN,
|
||||
PRESENT,
|
||||
TITLE,
|
||||
SUBTITLE,
|
||||
MAP
|
||||
};
|
||||
|
||||
struct AnimPlot {
|
||||
uint8 x, y;
|
||||
uint8 r, g, b, a;
|
||||
};
|
||||
|
||||
struct AnimElement {
|
||||
void shufflePlotData();
|
||||
|
||||
int _rx, _ry; // screen/source x and y
|
||||
int _rw, _rh; // source width and height
|
||||
AnimType _method; // render method
|
||||
int _animStep; // tracks animation position
|
||||
int _animStepMax;
|
||||
int _timeBase; // initial animation time
|
||||
uint32 _timeDelay; // delay before rendering begins
|
||||
int _timeDuration; // total animation time
|
||||
Image *_srcImage; // storage for the source image
|
||||
Image *_destImage; // storage for the animation frame
|
||||
Std::vector <AnimPlot> _plotData; // plot data
|
||||
bool _prescaled;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the intro element to the element list
|
||||
*/
|
||||
void addTitle(int x, int y, int w, int h, AnimType method, uint32 delay, int duration);
|
||||
|
||||
/**
|
||||
* The title element has finished drawing all frames, so delete, remove,
|
||||
* or free data that is no longer needed
|
||||
*/
|
||||
void compactTitle();
|
||||
|
||||
/**
|
||||
* Scale the animation canvas, then draw it to the screen
|
||||
*/
|
||||
void drawTitle();
|
||||
|
||||
/**
|
||||
* Get the source data for title elements that have already been initialized
|
||||
*/
|
||||
void getTitleSourceData();
|
||||
|
||||
/**
|
||||
* skip the remaining titles
|
||||
*/
|
||||
void skipTitles();
|
||||
|
||||
Std::vector<AnimElement> _titles; // list of title elements
|
||||
Std::vector<AnimElement>::iterator _title; // current title element
|
||||
|
||||
int _transparentIndex; // palette index for transparency
|
||||
RGBA _transparentColor; // palette color for transparency
|
||||
|
||||
bool _bSkipTitles;
|
||||
|
||||
// Temporary place-holder for settings changes
|
||||
SettingsData _settingsChanged;
|
||||
};
|
||||
|
||||
extern IntroController *g_intro;
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
120
engines/ultima/ultima4/controllers/key_handler_controller.cpp
Normal file
120
engines/ultima/ultima4/controllers/key_handler_controller.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/* 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 "ultima/ultima4/controllers/key_handler_controller.h"
|
||||
#include "ultima/ultima4/core/utils.h"
|
||||
#include "ultima/ultima4/events/event_handler.h"
|
||||
#include "ultima/ultima4/game/context.h"
|
||||
#include "ultima/ultima4/ultima4.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
|
||||
KeyHandler::KeyHandler(Callback func, void *d, bool asyncronous) :
|
||||
_handler(func),
|
||||
_async(asyncronous),
|
||||
_data(d) {
|
||||
}
|
||||
|
||||
bool KeyHandler::globalHandler(int key) {
|
||||
if (key == Common::KEYCODE_F5) {
|
||||
(void)g_ultima->saveGameDialog();
|
||||
} else if (key == Common::KEYCODE_F7) {
|
||||
(void)g_ultima->loadGameDialog();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KeyHandler::defaultHandler(int key, void *data) {
|
||||
bool valid = true;
|
||||
|
||||
switch (key) {
|
||||
case '`':
|
||||
if (g_context && g_context->_location)
|
||||
debug(1, "x = %d, y = %d, level = %d, tile = %d (%s)\n", g_context->_location->_coords.x, g_context->_location->_coords.y, g_context->_location->_coords.z, g_context->_location->_map->translateToRawTileIndex(*g_context->_location->_map->tileAt(g_context->_location->_coords, WITH_OBJECTS)), g_context->_location->_map->tileTypeAt(g_context->_location->_coords, WITH_OBJECTS)->getName().c_str());
|
||||
break;
|
||||
default:
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool KeyHandler::ignoreKeys(int key, void *data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KeyHandler::handle(int key) {
|
||||
bool processed = false;
|
||||
if (!isKeyIgnored(key)) {
|
||||
processed = globalHandler(key);
|
||||
if (!processed)
|
||||
processed = _handler(key, _data);
|
||||
}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
bool KeyHandler::isKeyIgnored(int key) {
|
||||
switch (key) {
|
||||
case Common::KEYCODE_RSHIFT:
|
||||
case Common::KEYCODE_LSHIFT:
|
||||
case Common::KEYCODE_RCTRL:
|
||||
case Common::KEYCODE_LCTRL:
|
||||
case Common::KEYCODE_RALT:
|
||||
case Common::KEYCODE_LALT:
|
||||
case Common::KEYCODE_RMETA:
|
||||
case Common::KEYCODE_LMETA:
|
||||
case Common::KEYCODE_TAB:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool KeyHandler::operator==(Callback cb) const {
|
||||
return (_handler == cb) ? true : false;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
KeyHandlerController::KeyHandlerController(KeyHandler *handler) {
|
||||
this->_handler = handler;
|
||||
}
|
||||
|
||||
KeyHandlerController::~KeyHandlerController() {
|
||||
delete _handler;
|
||||
}
|
||||
|
||||
bool KeyHandlerController::keyPressed(int key) {
|
||||
assertMsg(_handler != nullptr, "key handler must be initialized");
|
||||
return _handler->handle(key);
|
||||
}
|
||||
|
||||
KeyHandler *KeyHandlerController::getKeyHandler() {
|
||||
return _handler;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
119
engines/ultima/ultima4/controllers/key_handler_controller.h
Normal file
119
engines/ultima/ultima4/controllers/key_handler_controller.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_KEY_HANDLER_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_KEY_HANDLER_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/controller.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
/**
|
||||
* A class for handling keystrokes.
|
||||
*/
|
||||
class KeyHandler {
|
||||
public:
|
||||
virtual ~KeyHandler() {}
|
||||
|
||||
/* Typedefs */
|
||||
typedef bool (*Callback)(int, void *);
|
||||
|
||||
/** Additional information to be passed as data param for read buffer key handler */
|
||||
typedef struct ReadBuffer {
|
||||
int (*_handleBuffer)(Common::String *);
|
||||
Common::String *_buffer;
|
||||
int _bufferLen;
|
||||
int _screenX, _screenY;
|
||||
} ReadBuffer;
|
||||
|
||||
/** Additional information to be passed as data param for get choice key handler */
|
||||
typedef struct GetChoice {
|
||||
Common::String _choices;
|
||||
int (*_handleChoice)(int);
|
||||
} GetChoice;
|
||||
|
||||
/* Constructors */
|
||||
KeyHandler(Callback func, void *data = nullptr, bool asyncronous = true);
|
||||
|
||||
/**
|
||||
* Handles any and all keystrokes.
|
||||
* Generally used to exit the application, switch applications,
|
||||
* minimize, maximize, etc.
|
||||
*/
|
||||
static bool globalHandler(int key);
|
||||
|
||||
/* Static default key handler functions */
|
||||
/**
|
||||
* A default key handler that should be valid everywhere
|
||||
*/
|
||||
static bool defaultHandler(int key, void *data);
|
||||
|
||||
/**
|
||||
* A key handler that ignores keypresses
|
||||
*/
|
||||
static bool ignoreKeys(int key, void *data);
|
||||
|
||||
/* Operators */
|
||||
bool operator==(Callback cb) const;
|
||||
|
||||
/* Member functions */
|
||||
/**
|
||||
* Handles a keypress.
|
||||
* First it makes sure the key combination is not ignored
|
||||
* by the current key handler. Then, it passes the keypress
|
||||
* through the global key handler. If the global handler
|
||||
* does not process the keystroke, then the key handler
|
||||
* handles it itself by calling its handler callback function.
|
||||
*/
|
||||
bool handle(int key);
|
||||
|
||||
/**
|
||||
* Returns true if the key or key combination is always ignored by xu4
|
||||
*/
|
||||
virtual bool isKeyIgnored(int key);
|
||||
|
||||
protected:
|
||||
Callback _handler;
|
||||
bool _async;
|
||||
void *_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* A controller that wraps a keyhander function. Keyhandlers are
|
||||
* deprecated -- please use a controller instead.
|
||||
*/
|
||||
class KeyHandlerController : public Controller {
|
||||
public:
|
||||
KeyHandlerController(KeyHandler *handler);
|
||||
~KeyHandlerController();
|
||||
|
||||
bool keyPressed(int key) override;
|
||||
KeyHandler *getKeyHandler();
|
||||
|
||||
private:
|
||||
KeyHandler *_handler;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
121
engines/ultima/ultima4/controllers/menu_controller.cpp
Normal file
121
engines/ultima/ultima4/controllers/menu_controller.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/* 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 "ultima/ultima4/controllers/menu_controller.h"
|
||||
#include "ultima/ultima4/events/event_handler.h"
|
||||
#include "ultima/ultima4/views/menu.h"
|
||||
#include "ultima/ultima4/views/textview.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
MenuController::MenuController(Menu *menu, TextView *view) :
|
||||
WaitableController<void *>(nullptr) {
|
||||
this->_menu = menu;
|
||||
this->_view = view;
|
||||
}
|
||||
|
||||
void MenuController::setActive() {
|
||||
MetaEngine::setKeybindingMode(KBMODE_MENU);
|
||||
}
|
||||
|
||||
void MenuController::keybinder(KeybindingAction action) {
|
||||
bool cursorOn = _view->getCursorEnabled();
|
||||
|
||||
if (cursorOn)
|
||||
_view->disableCursor();
|
||||
|
||||
switch (action) {
|
||||
case KEYBIND_UP:
|
||||
_menu->prev();
|
||||
break;
|
||||
case KEYBIND_DOWN:
|
||||
_menu->next();
|
||||
break;
|
||||
case KEYBIND_LEFT:
|
||||
case KEYBIND_RIGHT:
|
||||
case KEYBIND_INTERACT: {
|
||||
MenuEvent::Type menuAction = MenuEvent::ACTIVATE;
|
||||
|
||||
if (action == KEYBIND_LEFT)
|
||||
menuAction = MenuEvent::DECREMENT;
|
||||
else if (action == KEYBIND_RIGHT)
|
||||
menuAction = MenuEvent::INCREMENT;
|
||||
_menu->activateItem(-1, menuAction);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_menu->show(_view);
|
||||
|
||||
if (cursorOn)
|
||||
_view->enableCursor();
|
||||
_view->update();
|
||||
|
||||
if (_menu->getClosed())
|
||||
doneWaiting();
|
||||
}
|
||||
|
||||
bool MenuController::keyPressed(int key) {
|
||||
bool handled = true;
|
||||
bool cursorOn = _view->getCursorEnabled();
|
||||
|
||||
if (cursorOn)
|
||||
_view->disableCursor();
|
||||
|
||||
handled = _menu->activateItemByShortcut(key, MenuEvent::ACTIVATE);
|
||||
|
||||
_menu->show(_view);
|
||||
|
||||
if (cursorOn)
|
||||
_view->enableCursor();
|
||||
_view->update();
|
||||
|
||||
if (_menu->getClosed())
|
||||
doneWaiting();
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
bool MenuController::mousePressed(const Common::Point &mousePos) {
|
||||
bool cursorOn = _view->getCursorEnabled();
|
||||
|
||||
if (cursorOn)
|
||||
_view->disableCursor();
|
||||
|
||||
_menu->activateItemAtPos(_view, mousePos);
|
||||
|
||||
_menu->show(_view);
|
||||
|
||||
if (cursorOn)
|
||||
_view->enableCursor();
|
||||
_view->update();
|
||||
|
||||
if (_menu->getClosed())
|
||||
doneWaiting();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
68
engines/ultima/ultima4/controllers/menu_controller.h
Normal file
68
engines/ultima/ultima4/controllers/menu_controller.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_MENU_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_MENU_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/controller.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
class Menu;
|
||||
class TextView;
|
||||
|
||||
/**
|
||||
* This class controls a menu. The value field of WaitableController
|
||||
* isn't used.
|
||||
*/
|
||||
class MenuController : public WaitableController<void *> {
|
||||
public:
|
||||
MenuController(Menu *menu, TextView *view);
|
||||
|
||||
/**
|
||||
* Called when a controller is made active
|
||||
*/
|
||||
void setActive() override;
|
||||
|
||||
/**
|
||||
* Handles keybinder actions
|
||||
*/
|
||||
void keybinder(KeybindingAction action) override;
|
||||
|
||||
/**
|
||||
* Key was pressed
|
||||
*/
|
||||
bool keyPressed(int key) override;
|
||||
|
||||
/**
|
||||
* Mouse button was pressed
|
||||
*/
|
||||
bool mousePressed(const Common::Point &mousePos) override;
|
||||
protected:
|
||||
Menu *_menu;
|
||||
TextView *_view;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
/* 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 "ultima/ultima4/controllers/read_choice_controller.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
|
||||
ReadChoiceController::ReadChoiceController(const Common::String &choices) :
|
||||
WaitableController<int>(-1) {
|
||||
_choices = choices;
|
||||
}
|
||||
|
||||
bool ReadChoiceController::keyPressed(int key) {
|
||||
// Common::isUpper() accepts 1-byte characters, yet the modifier keys
|
||||
// (ALT, SHIFT, ETC) produce values beyond 255
|
||||
if ((key <= 0x7F) && (Common::isUpper(key)))
|
||||
key = tolower(key);
|
||||
|
||||
_value = key;
|
||||
|
||||
if (_choices.empty() || _choices.findFirstOf(_value) < _choices.size()) {
|
||||
// If the value is printable, display it
|
||||
if (!Common::isSpace(key))
|
||||
g_screen->screenMessage("%c", toupper(key));
|
||||
doneWaiting();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ReadChoiceController::keybinder(KeybindingAction action) {
|
||||
if (action == KEYBIND_ESCAPE && _choices.contains('\x1B')) {
|
||||
_value = 27;
|
||||
doneWaiting();
|
||||
} else {
|
||||
WaitableController<int>::keybinder(action);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char ReadChoiceController::get(const Common::String &choices, EventHandler *eh) {
|
||||
if (!eh)
|
||||
eh = eventHandler;
|
||||
|
||||
ReadChoiceController ctrl(choices);
|
||||
eh->pushController(&ctrl);
|
||||
return ctrl.waitFor();
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
49
engines/ultima/ultima4/controllers/read_choice_controller.h
Normal file
49
engines/ultima/ultima4/controllers/read_choice_controller.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_READ_CHOICE_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_READ_CHOICE_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/controller.h"
|
||||
#include "ultima/ultima4/events/event_handler.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
/**
|
||||
* A controller to read a single key from a provided list.
|
||||
*/
|
||||
class ReadChoiceController : public WaitableController<int> {
|
||||
public:
|
||||
ReadChoiceController(const Common::String &choices);
|
||||
bool keyPressed(int key) override;
|
||||
void keybinder(KeybindingAction action) override;
|
||||
|
||||
static char get(const Common::String &choices, EventHandler *eh = nullptr);
|
||||
|
||||
protected:
|
||||
Common::String _choices;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
64
engines/ultima/ultima4/controllers/read_dir_controller.cpp
Normal file
64
engines/ultima/ultima4/controllers/read_dir_controller.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
/* 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 "ultima/ultima4/controllers/read_dir_controller.h"
|
||||
#include "ultima/ultima4/map/direction.h"
|
||||
#include "ultima/ultima4/metaengine.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
|
||||
ReadDirController::ReadDirController() : WaitableController<Direction>(DIR_NONE) {
|
||||
}
|
||||
|
||||
void ReadDirController::setActive() {
|
||||
// Special mode for inputing directions
|
||||
MetaEngine::setKeybindingMode(KBMODE_DIRECTION);
|
||||
}
|
||||
|
||||
void ReadDirController::keybinder(KeybindingAction action) {
|
||||
switch (action) {
|
||||
case KEYBIND_UP:
|
||||
_value = DIR_NORTH;
|
||||
break;
|
||||
case KEYBIND_DOWN:
|
||||
_value = DIR_SOUTH;
|
||||
break;
|
||||
case KEYBIND_LEFT:
|
||||
_value = DIR_WEST;
|
||||
break;
|
||||
case KEYBIND_RIGHT:
|
||||
_value = DIR_EAST;
|
||||
break;
|
||||
case KEYBIND_ESCAPE:
|
||||
_value = DIR_NONE;
|
||||
doneWaiting();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
doneWaiting();
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
52
engines/ultima/ultima4/controllers/read_dir_controller.h
Normal file
52
engines/ultima/ultima4/controllers/read_dir_controller.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_READ_DIR_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_READ_DIR_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/controller.h"
|
||||
#include "ultima/ultima4/map/direction.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
/**
|
||||
* A controller to read a direction enter with the arrow keys.
|
||||
*/
|
||||
class ReadDirController : public WaitableController<Direction> {
|
||||
public:
|
||||
ReadDirController();
|
||||
|
||||
/**
|
||||
* Called when a controller is made active
|
||||
*/
|
||||
void setActive() override;
|
||||
|
||||
/**
|
||||
* Handles keybinder actions
|
||||
*/
|
||||
void keybinder(KeybindingAction action) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
45
engines/ultima/ultima4/controllers/read_int_controller.cpp
Normal file
45
engines/ultima/ultima4/controllers/read_int_controller.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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 "ultima/ultima4/controllers/read_int_controller.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
ReadIntController::ReadIntController(int maxlen, int screenX, int screenY) :
|
||||
ReadStringController(maxlen, screenX, screenY, "0123456789 \n\r\010") {}
|
||||
|
||||
int ReadIntController::get(int maxlen, int screenX, int screenY, EventHandler *eh) {
|
||||
if (!eh)
|
||||
eh = eventHandler;
|
||||
|
||||
ReadIntController ctrl(maxlen, screenX, screenY);
|
||||
eh->pushController(&ctrl);
|
||||
ctrl.waitFor();
|
||||
return ctrl.getInt();
|
||||
}
|
||||
|
||||
int ReadIntController::getInt() const {
|
||||
return static_cast<int>(strtol(_value.c_str(), nullptr, 10));
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
45
engines/ultima/ultima4/controllers/read_int_controller.h
Normal file
45
engines/ultima/ultima4/controllers/read_int_controller.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_READ_INT_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_READ_INT_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/read_string_controller.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
/**
|
||||
* A controller to read a integer, terminated by the enter key.
|
||||
* Non-numeric keys are ignored.
|
||||
*/
|
||||
class ReadIntController : public ReadStringController {
|
||||
public:
|
||||
ReadIntController(int maxlen, int screenX, int screenY);
|
||||
|
||||
static int get(int maxlen, int screenX, int screenY, EventHandler *eh = nullptr);
|
||||
int getInt() const;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
/* 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 "ultima/ultima4/controllers/read_player_controller.h"
|
||||
#include "ultima/ultima4/filesys/savegame.h"
|
||||
#include "ultima/ultima4/ultima4.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
ReadPlayerController::ReadPlayerController() : ReadChoiceController("12345678 \033\n") {
|
||||
#ifdef IOS_ULTIMA4
|
||||
U4IOS::beginCharacterChoiceDialog();
|
||||
#endif
|
||||
}
|
||||
|
||||
ReadPlayerController::~ReadPlayerController() {
|
||||
#ifdef IOS_ULTIMA4
|
||||
U4IOS::endCharacterChoiceDialog();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ReadPlayerController::keyPressed(int key) {
|
||||
bool valid = ReadChoiceController::keyPressed(key);
|
||||
if (valid) {
|
||||
if (_value < '1' ||
|
||||
_value > ('0' + g_ultima->_saveGame->_members))
|
||||
_value = '0';
|
||||
} else {
|
||||
_value = '0';
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
int ReadPlayerController::getPlayer() {
|
||||
return _value == 27 ? -1 : _value - '1';
|
||||
}
|
||||
|
||||
int ReadPlayerController::waitFor() {
|
||||
ReadChoiceController::waitFor();
|
||||
return getPlayer();
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
46
engines/ultima/ultima4/controllers/read_player_controller.h
Normal file
46
engines/ultima/ultima4/controllers/read_player_controller.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_READ_PLAYER_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_READ_PLAYER_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/read_choice_controller.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
/**
|
||||
* A controller to read a player number.
|
||||
*/
|
||||
class ReadPlayerController : public ReadChoiceController {
|
||||
public:
|
||||
ReadPlayerController();
|
||||
~ReadPlayerController();
|
||||
bool keyPressed(int key) override;
|
||||
|
||||
int getPlayer();
|
||||
int waitFor() override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
112
engines/ultima/ultima4/controllers/read_string_controller.cpp
Normal file
112
engines/ultima/ultima4/controllers/read_string_controller.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
/* 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 "ultima/ultima4/controllers/read_string_controller.h"
|
||||
#include "ultima/ultima4/game/context.h"
|
||||
#include "ultima/ultima4/gfx/screen.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
ReadStringController::ReadStringController(int maxlen, int screenX, int screenY,
|
||||
const Common::String &accepted_chars) : WaitableController<Common::String>("") {
|
||||
_maxLen = maxlen;
|
||||
_screenX = screenX;
|
||||
_screenY = screenY;
|
||||
_view = nullptr;
|
||||
_accepted = accepted_chars;
|
||||
}
|
||||
|
||||
ReadStringController::ReadStringController(int maxlen, TextView *view,
|
||||
const Common::String &accepted_chars) : WaitableController<Common::String>("") {
|
||||
_maxLen = maxlen;
|
||||
_screenX = view->getCursorX();
|
||||
_screenY = view->getCursorY();
|
||||
_view = view;
|
||||
_accepted = accepted_chars;
|
||||
}
|
||||
|
||||
bool ReadStringController::keyPressed(int key) {
|
||||
int valid = true, len = _value.size();
|
||||
size_t pos = Common::String::npos;
|
||||
|
||||
if (key < 0x80)
|
||||
pos = _accepted.findFirstOf(key);
|
||||
|
||||
if (pos != Common::String::npos) {
|
||||
if (key == Common::KEYCODE_BACKSPACE) {
|
||||
if (len > 0) {
|
||||
/* remove the last character */
|
||||
_value.erase(len - 1, 1);
|
||||
|
||||
if (_view) {
|
||||
_view->textAt(_screenX + len - 1, _screenY, " ");
|
||||
_view->setCursorPos(_screenX + len - 1, _screenY, true);
|
||||
} else {
|
||||
g_screen->screenHideCursor();
|
||||
g_screen->screenTextAt(_screenX + len - 1, _screenY, " ");
|
||||
g_screen->screenSetCursorPos(_screenX + len - 1, _screenY);
|
||||
g_screen->screenShowCursor();
|
||||
}
|
||||
}
|
||||
} else if (key == '\n' || key == '\r') {
|
||||
doneWaiting();
|
||||
} else if (len < _maxLen) {
|
||||
/* add a character to the end */
|
||||
_value += key;
|
||||
|
||||
if (_view) {
|
||||
_view->textAt(_screenX + len, _screenY, "%c", key);
|
||||
} else {
|
||||
g_screen->screenHideCursor();
|
||||
g_screen->screenTextAt(_screenX + len, _screenY, "%c", key);
|
||||
g_screen->screenSetCursorPos(_screenX + len + 1, _screenY);
|
||||
g_context->_col = len + 1;
|
||||
g_screen->screenShowCursor();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
return valid || KeyHandler::defaultHandler(key, nullptr);
|
||||
}
|
||||
|
||||
Common::String ReadStringController::get(int maxlen, int screenX, int screenY, EventHandler *eh) {
|
||||
if (!eh)
|
||||
eh = eventHandler;
|
||||
|
||||
ReadStringController ctrl(maxlen, screenX, screenY);
|
||||
eh->pushController(&ctrl);
|
||||
return ctrl.waitFor();
|
||||
}
|
||||
|
||||
Common::String ReadStringController::get(int maxlen, TextView *view, EventHandler *eh) {
|
||||
if (!eh)
|
||||
eh = eventHandler;
|
||||
|
||||
ReadStringController ctrl(maxlen, view);
|
||||
eh->pushController(&ctrl);
|
||||
return ctrl.waitFor();
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
64
engines/ultima/ultima4/controllers/read_string_controller.h
Normal file
64
engines/ultima/ultima4/controllers/read_string_controller.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_READ_STRING_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_READ_STRING_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/controller.h"
|
||||
#include "ultima/ultima4/events/event_handler.h"
|
||||
#include "ultima/ultima4/views/textview.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
/**
|
||||
* A controller to read a Common::String, terminated by the enter key.
|
||||
*/
|
||||
class ReadStringController : public WaitableController<Common::String> {
|
||||
public:
|
||||
/**
|
||||
* @param maxlen the maximum length of the Common::String
|
||||
* @param screenX the screen column where to begin input
|
||||
* @param screenY the screen row where to begin input
|
||||
* @param accepted_chars a Common::String characters to be accepted for input
|
||||
*/
|
||||
ReadStringController(int maxlen, int screenX, int screenY, const Common::String &accepted_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 \n\r\010");
|
||||
ReadStringController(int maxlen, TextView *view, const Common::String &accepted_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 \n\r\010");
|
||||
bool keyPressed(int key) override;
|
||||
|
||||
static Common::String get(int maxlen, int screenX, int screenY, EventHandler *eh = nullptr);
|
||||
static Common::String get(int maxlen, TextView *view, EventHandler *eh = nullptr);
|
||||
#ifdef IOS_ULTIMA4
|
||||
void setValue(const Common::String &utf8StringValue) {
|
||||
value = utf8StringValue;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
int _maxLen, _screenX, _screenY;
|
||||
TextView *_view;
|
||||
Common::String _accepted;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
/* 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 "ultima/ultima4/controllers/reagents_menu_controller.h"
|
||||
#include "ultima/ultima4/views/menu.h"
|
||||
#include "ultima/ultima4/game/spell.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
bool ReagentsMenuController::keyPressed(int key) {
|
||||
switch (key) {
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h': {
|
||||
// Select the corresponding reagent (if visible)
|
||||
Menu::MenuItemList::iterator mi = _menu->getById(key - 'a');
|
||||
if ((*mi)->isVisible()) {
|
||||
_menu->setCurrent(_menu->getById(key - 'a'));
|
||||
keyPressed(Common::KEYCODE_SPACE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return MenuController::keyPressed(key);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReagentsMenuController::keybinder(KeybindingAction action) {
|
||||
switch (action) {
|
||||
case KEYBIND_ESCAPE:
|
||||
_ingredients->revert();
|
||||
eventHandler->setControllerDone();
|
||||
break;
|
||||
|
||||
case KEYBIND_UP:
|
||||
_menu->prev();
|
||||
break;
|
||||
|
||||
case KEYBIND_DOWN:
|
||||
_menu->next();
|
||||
break;
|
||||
|
||||
case KEYBIND_LEFT:
|
||||
case KEYBIND_RIGHT:
|
||||
if (_menu->isVisible()) {
|
||||
MenuItem *item = *_menu->getCurrent();
|
||||
|
||||
// change whether or not it's selected
|
||||
item->setSelected(!item->isSelected());
|
||||
|
||||
if (item->isSelected())
|
||||
_ingredients->addReagent((Reagent)item->getId());
|
||||
else
|
||||
_ingredients->removeReagent((Reagent)item->getId());
|
||||
}
|
||||
break;
|
||||
|
||||
case KEYBIND_INTERACT:
|
||||
eventHandler->setControllerDone();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
@@ -0,0 +1,54 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_REAGENTS_MENU_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_REAGENTS_MENU_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/menu_controller.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
class Ingredients;
|
||||
|
||||
/**
|
||||
* Controller for the reagents menu used when mixing spells. Fills
|
||||
* the passed in Ingredients with the selected reagents.
|
||||
*/
|
||||
class ReagentsMenuController : public MenuController {
|
||||
public:
|
||||
ReagentsMenuController(Menu *menu, Ingredients *i, TextView *view) : MenuController(menu, view), _ingredients(i) { }
|
||||
|
||||
/**
|
||||
* Handles spell mixing for the Ultima V-style menu-system
|
||||
*/
|
||||
bool keyPressed(int key) override;
|
||||
|
||||
void keybinder(KeybindingAction action) override;
|
||||
|
||||
private:
|
||||
Ingredients *_ingredients;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
51
engines/ultima/ultima4/controllers/wait_controller.cpp
Normal file
51
engines/ultima/ultima4/controllers/wait_controller.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/* 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 "ultima/ultima4/controllers/wait_controller.h"
|
||||
#include "ultima/ultima4/events/event_handler.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
WaitController::WaitController(uint c) : Controller(), _cycles(c), _current(0) {
|
||||
}
|
||||
|
||||
void WaitController::timerFired() {
|
||||
if (++_current >= _cycles) {
|
||||
_current = 0;
|
||||
eventHandler->setControllerDone(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool WaitController::keyPressed(int key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void WaitController::wait() {
|
||||
Controller_startWait();
|
||||
}
|
||||
|
||||
void WaitController::setCycles(int c) {
|
||||
_cycles = c;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
51
engines/ultima/ultima4/controllers/wait_controller.h
Normal file
51
engines/ultima/ultima4/controllers/wait_controller.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_WAIT_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_WAIT_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/controller.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
/**
|
||||
* A controller to pause for a given length of time, ignoring all
|
||||
* keyboard input.
|
||||
*/
|
||||
class WaitController : public Controller {
|
||||
public:
|
||||
WaitController(uint cycles);
|
||||
bool keyPressed(int key) override;
|
||||
void timerFired() override;
|
||||
|
||||
void wait();
|
||||
void setCycles(int c);
|
||||
|
||||
private:
|
||||
uint _cycles;
|
||||
uint _current;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
71
engines/ultima/ultima4/controllers/ztats_controller.cpp
Normal file
71
engines/ultima/ultima4/controllers/ztats_controller.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/* 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 "ultima/ultima4/controllers/ztats_controller.h"
|
||||
#include "ultima/ultima4/events/event_handler.h"
|
||||
#include "ultima/ultima4/game/context.h"
|
||||
#include "ultima/ultima4/views/stats.h"
|
||||
#include "ultima/ultima4/ultima4.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
bool ZtatsController::keyPressed(int key) {
|
||||
switch (key) {
|
||||
case Common::KEYCODE_RETURN:
|
||||
keybinder(KEYBIND_ESCAPE);
|
||||
return true;
|
||||
case Common::KEYCODE_UP:
|
||||
case Common::KEYCODE_LEFT:
|
||||
g_context->_stats->prevItem();
|
||||
return true;
|
||||
case Common::KEYCODE_DOWN:
|
||||
case Common::KEYCODE_RIGHT:
|
||||
g_context->_stats->nextItem();
|
||||
return true;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
if (g_ultima->_saveGame->_members >= key - '0')
|
||||
g_context->_stats->setView(StatsView(STATS_CHAR1 + key - '1'));
|
||||
return true;
|
||||
case '0':
|
||||
g_context->_stats->setView(StatsView(STATS_WEAPONS));
|
||||
return true;
|
||||
default:
|
||||
return KeyHandler::defaultHandler(key, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void ZtatsController::keybinder(KeybindingAction action) {
|
||||
if (action == KEYBIND_ESCAPE) {
|
||||
g_context->_stats->setView(StatsView(STATS_PARTY_OVERVIEW));
|
||||
doneWaiting();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
44
engines/ultima/ultima4/controllers/ztats_controller.h
Normal file
44
engines/ultima/ultima4/controllers/ztats_controller.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA4_CONTROLLERS_ZTATS_CONTROLLER_H
|
||||
#define ULTIMA4_CONTROLLERS_ZTATS_CONTROLLER_H
|
||||
|
||||
#include "ultima/ultima4/controllers/controller.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima4 {
|
||||
|
||||
/**
|
||||
* Controls interaction while Ztats are being displayed.
|
||||
*/
|
||||
class ZtatsController : public WaitableController<void *> {
|
||||
public:
|
||||
ZtatsController() : WaitableController<void *>(nullptr) {}
|
||||
|
||||
bool keyPressed(int key) override;
|
||||
void keybinder(KeybindingAction action) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user