aboutsummaryrefslogtreecommitdiff
path: root/sword2/mouse.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sword2/mouse.cpp')
-rw-r--r--sword2/mouse.cpp520
1 files changed, 377 insertions, 143 deletions
diff --git a/sword2/mouse.cpp b/sword2/mouse.cpp
index c0062ba635..be8953c254 100644
--- a/sword2/mouse.cpp
+++ b/sword2/mouse.cpp
@@ -27,13 +27,13 @@
#include "sword2/logic.h"
#include "sword2/maketext.h"
#include "sword2/memory.h"
+#include "sword2/mouse.h"
#include "sword2/resman.h"
#include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
namespace Sword2 {
-// pointer resource id's
+// Pointer resource id's
enum {
CROSHAIR = 18,
@@ -55,19 +55,132 @@ enum {
USE = 3100
};
+Mouse::Mouse(Sword2Engine *vm) {
+ _vm = vm;
+
+ setPos(0, 0);
+
+ _mouseTouching = 0;
+ _oldMouseTouching = 0;
+ _menuSelectedPos = 0;
+ _examiningMenuIcon = false;
+ _mousePointerRes = 0;
+ _mouseMode = 0;
+ _mouseStatus = false;
+ _mouseModeLocked = false;
+ _currentLuggageResource = 0;
+ _oldButton = 0;
+ _buttonClick = 0;
+ _pointerTextBlocNo = 0;
+ _playerActivityDelay = 0;
+ _realLuggageItem = 0;
+
+ _mouseSprite = NULL;
+ _mouseAnim = NULL;
+ _luggageAnim = NULL;
+
+ // For the menus
+ _totalTemp = 0;
+ memset(_tempList, 0, sizeof(_tempList));
+
+ _totalMasters = 0;
+ memset(_masterMenuList, 0, sizeof(_masterMenuList));
+ memset(_mouseList, 0, sizeof(_mouseList));
+
+ _iconCount = 0;
+
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < RDMENU_MAXPOCKETS; j++) {
+ _icons[i][j] = NULL;
+ _pocketStatus[i][j] = 0;
+ }
+
+ _menuStatus[i] = RDMENU_HIDDEN;
+ }
+}
+
+Mouse::~Mouse() {
+ free(_mouseAnim);
+ free(_luggageAnim);
+ for (int i = 0; i < 2; i++)
+ for (int j = 0; j < RDMENU_MAXPOCKETS; j++)
+ free(_icons[i][j]);
+}
+
+void Mouse::getPos(int &x, int &y) {
+ x = _pos.x;
+ y = _pos.y;
+}
+
+void Mouse::setPos(int x, int y) {
+ _pos.x = x;
+ _pos.y = y;
+}
+
/**
* Call at beginning of game loop
*/
-void Sword2Engine::resetMouseList(void) {
+void Mouse::resetMouseList() {
_curMouse = 1;
}
+void Mouse::registerMouse(ObjectMouse *ob_mouse, BuildUnit *build_unit) {
+ if (!ob_mouse->pointer)
+ return;
+
+ assert(_curMouse < TOTAL_mouse_list);
+
+ if (build_unit) {
+ _mouseList[_curMouse].x1 = build_unit->x;
+ _mouseList[_curMouse].y1 = build_unit->y;
+ _mouseList[_curMouse].x2 = build_unit->x + build_unit->scaled_width;
+ _mouseList[_curMouse].y2 = build_unit->y + build_unit->scaled_height;
+ } else {
+ _mouseList[_curMouse].x1 = ob_mouse->x1;
+ _mouseList[_curMouse].y1 = ob_mouse->y1;
+ _mouseList[_curMouse].x2 = ob_mouse->x2;
+ _mouseList[_curMouse].y2 = ob_mouse->y2;
+ }
+
+ _mouseList[_curMouse].priority = ob_mouse->priority;
+ _mouseList[_curMouse].pointer = ob_mouse->pointer;
+
+ // Check if pointer text field is set due to previous object using this
+ // slot (ie. not correct for this one)
+
+ // If 'pointer_text' field is set, but the 'id' field isn't same is
+ // current id then we don't want this "left over" pointer text
+
+ if (_mouseList[_curMouse].pointer_text && _mouseList[_curMouse].id != (int32) Logic::_scriptVars[ID])
+ _mouseList[_curMouse].pointer_text = 0;
+
+ // Get id from system variable 'id' which is correct for current object
+ _mouseList[_curMouse].id = Logic::_scriptVars[ID];
+
+ // Not using sprite as detection mask - this is only done from
+ // fnRegisterFrame()
+ _mouseList[_curMouse].anim_resource = 0;
+ _mouseList[_curMouse].anim_pc = 0;
+
+ _curMouse++;
+}
+
+void Mouse::registerPointerText(int32 text_id) {
+ assert(_curMouse < TOTAL_mouse_list);
+
+ // current object id - used for checking pointer_text when mouse area
+ // registered (in fnRegisterMouse and fnRegisterFrame)
+
+ _mouseList[_curMouse].id = Logic::_scriptVars[ID];
+ _mouseList[_curMouse].pointer_text = text_id;
+}
+
/**
* This function is called every game cycle.
*/
-void Sword2Engine::mouseEngine(void) {
+void Mouse::mouseEngine() {
monitorPlayerActivity();
clearPointerText();
@@ -109,7 +222,7 @@ void Sword2Engine::mouseEngine(void) {
systemMenuMouse();
break;
case MOUSE_holding:
- if (_mouseY < 400) {
+ if (_pos.y < 400) {
_mouseMode = MOUSE_normal;
debug(5, " releasing");
}
@@ -120,7 +233,7 @@ void Sword2Engine::mouseEngine(void) {
}
#if RIGHT_CLICK_CLEARS_LUGGAGE
-bool Sword2Engine::heldIsInInventory(void) {
+bool Mouse::heldIsInInventory() {
for (uint i = 0; i < _totalMasters; i++) {
if ((uint32) _masterMenuList[i].icon_resource == Logic::_scriptVars[OBJECT_HELD])
return true;
@@ -129,17 +242,17 @@ bool Sword2Engine::heldIsInInventory(void) {
}
#endif
-int Sword2Engine::menuClick(int menu_items) {
- if (_mouseX < RDMENU_ICONSTART)
+int Mouse::menuClick(int menu_items) {
+ if (_pos.x < RDMENU_ICONSTART)
return -1;
- if (_mouseX > RDMENU_ICONSTART + menu_items * (RDMENU_ICONWIDE + RDMENU_ICONSPACING) - RDMENU_ICONSPACING)
+ if (_pos.x > RDMENU_ICONSTART + menu_items * (RDMENU_ICONWIDE + RDMENU_ICONSPACING) - RDMENU_ICONSPACING)
return -1;
- return (_mouseX - RDMENU_ICONSTART) / (RDMENU_ICONWIDE + RDMENU_ICONSPACING);
+ return (_pos.x - RDMENU_ICONSTART) / (RDMENU_ICONWIDE + RDMENU_ICONSPACING);
}
-void Sword2Engine::systemMenuMouse(void) {
+void Mouse::systemMenuMouse(void) {
uint32 safe_looping_music_id;
MouseEvent *me;
int hit;
@@ -156,20 +269,20 @@ void Sword2Engine::systemMenuMouse(void) {
// If the mouse is moved off the menu, close it. Unless the player is
// dead, in which case the menu should always be visible.
- if (_mouseY > 0 && !Logic::_scriptVars[DEAD]) {
+ if (_pos.y > 0 && !Logic::_scriptVars[DEAD]) {
_mouseMode = MOUSE_normal;
- _graphics->hideMenu(RDMENU_TOP);
+ hideMenu(RDMENU_TOP);
return;
}
// Check if the user left-clicks anywhere in the menu area.
- me = mouseEvent();
+ me = _vm->mouseEvent();
if (!me || !(me->buttons & RD_LEFTBUTTONDOWN))
return;
- if (_mouseY > 0)
+ if (_pos.y > 0)
return;
hit = menuClick(ARRAYSIZE(icon_list));
@@ -186,46 +299,46 @@ void Sword2Engine::systemMenuMouse(void) {
for (int i = 0; i < ARRAYSIZE(icon_list); i++) {
if (i != hit) {
- icon = _resman->openResource(icon_list[i]) + sizeof(StandardHeader);
- _graphics->setMenuIcon(RDMENU_TOP, i, icon);
- _resman->closeResource(icon_list[i]);
+ icon = _vm->_resman->openResource(icon_list[i]) + sizeof(StandardHeader);
+ setMenuIcon(RDMENU_TOP, i, icon);
+ _vm->_resman->closeResource(icon_list[i]);
}
}
- _sound->pauseFx();
+ _vm->_sound->pauseFx();
// NB. Need to keep a safe copy of '_loopingMusicId' for savegame & for
// playing when returning from control panels because control panel
// music will overwrite it!
- safe_looping_music_id = _sound->getLoopingMusicId();
+ safe_looping_music_id = _vm->_sound->getLoopingMusicId();
pars[0] = 221;
pars[1] = FX_LOOP;
- _logic->fnPlayMusic(pars);
+ _vm->_logic->fnPlayMusic(pars);
// HACK: Restore proper looping_music_id
- _sound->setLoopingMusicId(safe_looping_music_id);
+ _vm->_sound->setLoopingMusicId(safe_looping_music_id);
- _graphics->processMenu();
+ processMenu();
// call the relevant screen
switch (hit) {
case 0:
- _gui->optionControl();
+ _vm->_gui->optionControl();
break;
case 1:
- _gui->quitControl();
+ _vm->_gui->quitControl();
break;
case 2:
- _gui->saveControl();
+ _vm->_gui->saveControl();
break;
case 3:
- _gui->restoreControl();
+ _vm->_gui->restoreControl();
break;
case 4:
- _gui->restartControl();
+ _vm->_gui->restartControl();
break;
}
@@ -233,7 +346,7 @@ void Sword2Engine::systemMenuMouse(void) {
if (!Logic::_scriptVars[DEAD]) {
_mouseMode = MOUSE_normal;
- _graphics->hideMenu(RDMENU_TOP);
+ hideMenu(RDMENU_TOP);
} else {
setMouse(NORMAL_MOUSE_ID);
buildSystemMenu();
@@ -241,35 +354,37 @@ void Sword2Engine::systemMenuMouse(void) {
// Back to the game again
- _graphics->processMenu();
+ processMenu();
// Reset game palette, but not after a successful restore or restart!
// See RestoreFromBuffer() in save_rest.cpp
- if (_thisScreen.new_palette != 99) {
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
+ if (screenInfo->new_palette != 99) {
// 0 means put back game screen palette; see build_display.cpp
- setFullPalette(0);
+ _vm->_screen->setFullPalette(0);
// Stop the engine fading in the restored screens palette
- _thisScreen.new_palette = 0;
+ screenInfo->new_palette = 0;
} else
- _thisScreen.new_palette = 1;
+ screenInfo->new_palette = 1;
- _sound->unpauseFx();
+ _vm->_sound->unpauseFx();
// If there was looping music before coming into the control panels
// then restart it! NB. If a game has been restored the music will be
// restarted twice, but this shouldn't cause any harm.
- if (_sound->getLoopingMusicId()) {
- pars[0] = _sound->getLoopingMusicId();
+ if (_vm->_sound->getLoopingMusicId()) {
+ pars[0] = _vm->_sound->getLoopingMusicId();
pars[1] = FX_LOOP;
- _logic->fnPlayMusic(pars);
+ _vm->_logic->fnPlayMusic(pars);
} else
- _logic->fnStopMusic(NULL);
+ _vm->_logic->fnStopMusic(NULL);
}
-void Sword2Engine::dragMouse(void) {
+void Mouse::dragMouse(void) {
byte buf1[NAME_LEN], buf2[NAME_LEN];
MouseEvent *me;
int hit;
@@ -278,9 +393,9 @@ void Sword2Engine::dragMouse(void) {
// objects in the scene, so if the mouse moves off the inventory menu,
// then close it.
- if (_mouseY < 400) {
+ if (_pos.y < 400) {
_mouseMode = MOUSE_normal;
- _graphics->hideMenu(RDMENU_BOTTOM);
+ hideMenu(RDMENU_BOTTOM);
return;
}
@@ -290,7 +405,7 @@ void Sword2Engine::dragMouse(void) {
// Now do the normal click stuff
- me = mouseEvent();
+ me = _vm->mouseEvent();
if (!me)
return;
@@ -327,24 +442,25 @@ void Sword2Engine::dragMouse(void) {
Logic::_scriptVars[RIGHT_BUTTON] = 0;
// These might be required by the action script about to be run
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
- Logic::_scriptVars[MOUSE_X] = _mouseX + _thisScreen.scroll_offset_x;
- Logic::_scriptVars[MOUSE_Y] = _mouseY + _thisScreen.scroll_offset_y;
+ Logic::_scriptVars[MOUSE_X] = _pos.x + screenInfo->scroll_offset_x;
+ Logic::_scriptVars[MOUSE_Y] = _pos.y + screenInfo->scroll_offset_y;
// For scripts to know what's been clicked. First used for
// 'room_13_turning_script' in object 'biscuits_13'
Logic::_scriptVars[CLICKED_ID] = _mouseTouching;
- _logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
+ _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
debug(2, "Used \"%s\" on \"%s\"",
- fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
- fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
+ _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
+ _vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
// Hide menu - back to normal menu mode
- _graphics->hideMenu(RDMENU_BOTTOM);
+ hideMenu(RDMENU_BOTTOM);
_mouseMode = MOUSE_normal;
return;
@@ -372,16 +488,16 @@ void Sword2Engine::dragMouse(void) {
// Otherwise, combine the two icons
Logic::_scriptVars[COMBINE_BASE] = _masterMenuList[hit].icon_resource;
- _logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
+ _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
// Turn off mouse now, to prevent player trying to click
// elsewhere BUT leave the bottom menu open
- noHuman();
+ hideMouse();
debug(2, "Used \"%s\" on \"%s\"",
- fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
- fetchObjectName(Logic::_scriptVars[COMBINE_BASE], buf2));
+ _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
+ _vm->fetchObjectName(Logic::_scriptVars[COMBINE_BASE], buf2));
}
// Refresh the menu
@@ -389,20 +505,20 @@ void Sword2Engine::dragMouse(void) {
buildMenu();
}
-void Sword2Engine::menuMouse(void) {
+void Mouse::menuMouse() {
byte buf[NAME_LEN];
MouseEvent *me;
int hit;
// If the mouse is moved off the menu, close it.
- if (_mouseY < 400) {
+ if (_pos.y < 400) {
_mouseMode = MOUSE_normal;
- _graphics->hideMenu(RDMENU_BOTTOM);
+ hideMenu(RDMENU_BOTTOM);
return;
}
- me = mouseEvent();
+ me = _vm->mouseEvent();
if (!me)
return;
@@ -426,7 +542,7 @@ void Sword2Engine::menuMouse(void) {
Logic::_scriptVars[EXIT_CLICK_ID] = 0;
- _logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
+ _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
// Refresh the menu
@@ -435,10 +551,10 @@ void Sword2Engine::menuMouse(void) {
// Turn off mouse now, to prevent player trying to click
// elsewhere BUT leave the bottom menu open
- noHuman();
+ hideMouse();
debug(2, "Right-click on \"%s\" icon",
- fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
+ _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
return;
}
@@ -466,11 +582,11 @@ void Sword2Engine::menuMouse(void) {
setLuggage(_masterMenuList[hit].luggage_resource);
debug(2, "Left-clicked on \"%s\" icon - switch to drag mode",
- fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
+ _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
}
}
-void Sword2Engine::normalMouse(void) {
+void Mouse::normalMouse(void) {
// The gane is playing and none of the menus are activated - but, we
// need to check if a menu is to start. Note, won't have luggage
@@ -480,7 +596,7 @@ void Sword2Engine::normalMouse(void) {
// big-object menu lock situation, of if the player is dragging an
// object.
- if (_mouseY < 0 && !_mouseModeLocked && !Logic::_scriptVars[OBJECT_HELD]) {
+ if (_pos.y < 0 && !_mouseModeLocked && !Logic::_scriptVars[OBJECT_HELD]) {
_mouseMode = MOUSE_system_menu;
if (_mouseTouching) {
@@ -499,7 +615,7 @@ void Sword2Engine::normalMouse(void) {
// Check if the cursor has moved onto the inventory menu area. No
// inventory in big-object menu lock situation,
- if (_mouseY > 399 && !_mouseModeLocked) {
+ if (_pos.y > 399 && !_mouseModeLocked) {
// If an object is being held, i.e. if the mouse cursor has a
// luggage, go to drag mode instead of menu mode, but the menu
// is still opened.
@@ -532,7 +648,7 @@ void Sword2Engine::normalMouse(void) {
mouseOnOff();
- me = mouseEvent();
+ me = _vm->mouseEvent();
if (!me)
return;
@@ -542,27 +658,29 @@ void Sword2Engine::normalMouse(void) {
// For debugging. We can draw a rectangle on the screen and see its
// coordinates. This was probably used to help defining hit areas.
- if (_debugger->_definingRectangles) {
- if (_debugger->_draggingRectangle == 0) {
+ if (_vm->_debugger->_definingRectangles) {
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
+ if (_vm->_debugger->_draggingRectangle == 0) {
// Not yet dragging a rectangle, so need click to start
if (button_down) {
// set both (x1,y1) and (x2,y2) to this point
- _debugger->_rectX1 = _debugger->_rectX2 = (uint32) _mouseX + _thisScreen.scroll_offset_x;
- _debugger->_rectY1 = _debugger->_rectY2 = (uint32) _mouseY + _thisScreen.scroll_offset_y;
- _debugger->_draggingRectangle = 1;
+ _vm->_debugger->_rectX1 = _vm->_debugger->_rectX2 = (uint32) _pos.x + screenInfo->scroll_offset_x;
+ _vm->_debugger->_rectY1 = _vm->_debugger->_rectY2 = (uint32) _pos.y + screenInfo->scroll_offset_y;
+ _vm->_debugger->_draggingRectangle = 1;
}
- } else if (_debugger->_draggingRectangle == 1) {
+ } else if (_vm->_debugger->_draggingRectangle == 1) {
// currently dragging a rectangle - click means reset
if (button_down) {
// lock rectangle, so you can let go of mouse
// to type in the coords
- _debugger->_draggingRectangle = 2;
+ _vm->_debugger->_draggingRectangle = 2;
} else {
// drag rectangle
- _debugger->_rectX2 = (uint32) _mouseX + _thisScreen.scroll_offset_x;
- _debugger->_rectY2 = (uint32) _mouseY + _thisScreen.scroll_offset_y;
+ _vm->_debugger->_rectX2 = (uint32) _pos.x + screenInfo->scroll_offset_x;
+ _vm->_debugger->_rectY2 = (uint32) _pos.y + screenInfo->scroll_offset_y;
}
} else {
// currently locked to avoid knocking out of place
@@ -570,7 +688,7 @@ void Sword2Engine::normalMouse(void) {
if (button_down) {
// click means reset - back to start again
- _debugger->_draggingRectangle = 0;
+ _vm->_debugger->_draggingRectangle = 0;
}
}
@@ -622,17 +740,18 @@ void Sword2Engine::normalMouse(void) {
}
// These might be required by the action script about to be run
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
- Logic::_scriptVars[MOUSE_X] = _mouseX + _thisScreen.scroll_offset_x;
- Logic::_scriptVars[MOUSE_Y] = _mouseY + _thisScreen.scroll_offset_y;
+ Logic::_scriptVars[MOUSE_X] = _pos.x + screenInfo->scroll_offset_x;
+ Logic::_scriptVars[MOUSE_Y] = _pos.y + screenInfo->scroll_offset_y;
if (_mouseTouching == Logic::_scriptVars[EXIT_CLICK_ID] && (me->buttons & RD_LEFTBUTTONDOWN)) {
// It's the exit double click situation. Let the existing
// interaction continue and start fading down. Switch the human
// off too
- _logic->fnNoHuman(NULL);
- _logic->fnFadeDown(NULL);
+ noHuman();
+ _vm->_logic->fnFadeDown(NULL);
// Tell the walker
@@ -669,24 +788,24 @@ void Sword2Engine::normalMouse(void) {
if (_mouseTouching == 2773 && !Logic::_scriptVars[LEFT_BUTTON]) {
warning("Working around elevator script bug");
} else
- _logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
+ _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
byte buf1[NAME_LEN], buf2[NAME_LEN];
if (Logic::_scriptVars[OBJECT_HELD])
debug(2, "Used \"%s\" on \"%s\"",
- fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
- fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
+ _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
+ _vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
else if (Logic::_scriptVars[LEFT_BUTTON])
debug(2, "Left-clicked on \"%s\"",
- fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
+ _vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
else // RIGHT BUTTON
debug(2, "Right-clicked on \"%s\"",
- fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
+ _vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
}
}
-void Sword2Engine::mouseOnOff(void) {
+void Mouse::mouseOnOff() {
// this handles the cursor graphic when moving on and off mouse areas
// it also handles the luggage thingy
@@ -698,7 +817,7 @@ void Sword2Engine::mouseOnOff(void) {
// don't detect objects that are hidden behind the menu bars (ie. in
// the scrolled-off areas of the screen)
- if (_mouseY < 0 || _mouseY > 399) {
+ if (_pos.y < 0 || _pos.y > 399) {
pointer_type = 0;
_mouseTouching = 0;
} else {
@@ -743,7 +862,7 @@ void Sword2Engine::mouseOnOff(void) {
} else {
byte buf[NAME_LEN];
- error("ERROR: mouse.pointer==0 for object %d (%s) - update logic script!", _mouseTouching, fetchObjectName(_mouseTouching, buf));
+ error("ERROR: mouse.pointer==0 for object %d (%s) - update logic script!", _mouseTouching, _vm->fetchObjectName(_mouseTouching, buf));
}
} else if (_oldMouseTouching && !_mouseTouching) {
// the cursor has moved off something - reset cursor to
@@ -783,55 +902,66 @@ void Sword2Engine::mouseOnOff(void) {
// screens
}
-void Sword2Engine::setMouse(uint32 res) {
+void Mouse::setMouse(uint32 res) {
// high level - whats the mouse - for the engine
_mousePointerRes = res;
if (res) {
- byte *icon = _resman->openResource(res) + sizeof(StandardHeader);
- uint32 len = _resman->fetchLen(res) - sizeof(StandardHeader);
+ byte *icon = _vm->_resman->openResource(res) + sizeof(StandardHeader);
+ uint32 len = _vm->_resman->fetchLen(res) - sizeof(StandardHeader);
// don't pulse the normal pointer - just do the regular anim
// loop
if (res == NORMAL_MOUSE_ID)
- _graphics->setMouseAnim(icon, len, RDMOUSE_NOFLASH);
+ setMouseAnim(icon, len, RDMOUSE_NOFLASH);
else
- _graphics->setMouseAnim(icon, len, RDMOUSE_FLASH);
+ setMouseAnim(icon, len, RDMOUSE_FLASH);
- _resman->closeResource(res);
+ _vm->_resman->closeResource(res);
} else {
// blank cursor
- _graphics->setMouseAnim(NULL, 0, 0);
+ setMouseAnim(NULL, 0, 0);
}
}
-void Sword2Engine::setLuggage(uint32 res) {
+void Mouse::setLuggage(uint32 res) {
_realLuggageItem = res;
if (res) {
- byte *icon = _resman->openResource(res) + sizeof(StandardHeader);
- uint32 len = _resman->fetchLen(res) - sizeof(StandardHeader);
+ byte *icon = _vm->_resman->openResource(res) + sizeof(StandardHeader);
+ uint32 len = _vm->_resman->fetchLen(res) - sizeof(StandardHeader);
- _graphics->setLuggageAnim(icon, len);
- _resman->closeResource(res);
+ setLuggageAnim(icon, len);
+ _vm->_resman->closeResource(res);
} else
- _graphics->setLuggageAnim(NULL, 0);
+ setLuggageAnim(NULL, 0);
}
-uint32 Sword2Engine::checkMouseList(void) {
- // Number of priorities subject to implementation needs
+void Mouse::setObjectHeld(uint32 res) {
+ setLuggage(res);
+ Logic::_scriptVars[OBJECT_HELD] = res;
+ _currentLuggageResource = res;
+
+ // mode locked - no menu available
+ _mouseModeLocked = true;
+}
+
+uint32 Mouse::checkMouseList() {
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
+ // Number of priorities subject to implementation needs
for (int priority = 0; priority < 10; priority++) {
for (uint i = 1; i < _curMouse; i++) {
// If the mouse pointer is over this
// mouse-detection-box
if (_mouseList[i].priority == priority &&
- _mouseX + _thisScreen.scroll_offset_x >= _mouseList[i].x1 &&
- _mouseX + _thisScreen.scroll_offset_x <= _mouseList[i].x2 &&
- _mouseY + _thisScreen.scroll_offset_y >= _mouseList[i].y1 &&
- _mouseY + _thisScreen.scroll_offset_y <= _mouseList[i].y2) {
+ _pos.x + screenInfo->scroll_offset_x >= _mouseList[i].x1 &&
+ _pos.x + screenInfo->scroll_offset_x <= _mouseList[i].x2 &&
+ _pos.y + screenInfo->scroll_offset_y >= _mouseList[i].y1 &&
+ _pos.y + screenInfo->scroll_offset_y <= _mouseList[i].y2) {
// Record id
_mouseTouching = _mouseList[i].id;
@@ -855,7 +985,7 @@ uint32 Sword2Engine::checkMouseList(void) {
#define POINTER_TEXT_WIDTH 640 // just in case!
#define POINTER_TEXT_PEN 184 // white
-void Sword2Engine::createPointerText(uint32 text_id, uint32 pointer_res) {
+void Mouse::createPointerText(uint32 text_id, uint32 pointer_res) {
uint32 local_text;
uint32 text_res;
byte *text;
@@ -863,7 +993,7 @@ void Sword2Engine::createPointerText(uint32 text_id, uint32 pointer_res) {
int16 xOffset, yOffset;
uint8 justification;
- if (!_gui->_pointerTextSelected || !text_id)
+ if (!_vm->_gui->_pointerTextSelected || !text_id)
return;
// Check what the pointer is, to set offsets correctly for text
@@ -993,30 +1123,30 @@ void Sword2Engine::createPointerText(uint32 text_id, uint32 pointer_res) {
local_text = text_id & 0xffff;
// open text file & get the line
- text = fetchTextLine(_resman->openResource(text_res), local_text);
+ text = _vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text);
// 'text+2' to skip the first 2 bytes which form the
// line reference number
- _pointerTextBlocNo = _fontRenderer->buildNewBloc(
- text + 2, _mouseX + xOffset,
- _mouseY + yOffset,
+ _pointerTextBlocNo = _vm->_fontRenderer->buildNewBloc(
+ text + 2, _pos.x + xOffset,
+ _pos.y + yOffset,
POINTER_TEXT_WIDTH, POINTER_TEXT_PEN,
RDSPR_TRANS | RDSPR_DISPLAYALIGN,
- _speechFontId, justification);
+ _vm->_speechFontId, justification);
// now ok to close the text file
- _resman->closeResource(text_res);
+ _vm->_resman->closeResource(text_res);
}
-void Sword2Engine::clearPointerText(void) {
+void Mouse::clearPointerText() {
if (_pointerTextBlocNo) {
- _fontRenderer->killTextBloc(_pointerTextBlocNo);
+ _vm->_fontRenderer->killTextBloc(_pointerTextBlocNo);
_pointerTextBlocNo = 0;
}
}
-void Sword2Engine::noHuman(void) {
+void Mouse::hideMouse() {
// leaves the menus open
// used by the system when clicking right on a menu item to examine
// it and when combining objects
@@ -1031,47 +1161,122 @@ void Sword2Engine::noHuman(void) {
setLuggage(0);
}
-void Sword2Engine::registerMouse(ObjectMouse *ob_mouse) {
- debug(5, "_curMouse = %d", _curMouse);
+void Mouse::noHuman() {
+ hideMouse();
+ clearPointerText();
- if (!ob_mouse->pointer)
- return;
+ // Must be normal mouse situation or a largely neutral situation -
+ // special menus use hideMouse()
- assert(_curMouse < TOTAL_mouse_list);
+ // Don't hide menu in conversations
+ if (Logic::_scriptVars[TALK_FLAG] == 0)
+ hideMenu(RDMENU_BOTTOM);
- _mouseList[_curMouse].x1 = ob_mouse->x1;
- _mouseList[_curMouse].y1 = ob_mouse->y1;
- _mouseList[_curMouse].x2 = ob_mouse->x2;
- _mouseList[_curMouse].y2 = ob_mouse->y2;
+ if (_mouseMode == MOUSE_system_menu) {
+ // Close menu
+ _mouseMode = MOUSE_normal;
+ hideMenu(RDMENU_TOP);
+ }
+}
- _mouseList[_curMouse].priority = ob_mouse->priority;
- _mouseList[_curMouse].pointer = ob_mouse->pointer;
+void Mouse::addHuman() {
+ // For logic scripts
+ Logic::_scriptVars[MOUSE_AVAILABLE] = 1;
- // Check if pointer text field is set due to previous object using this
- // slot (ie. not correct for this one)
+ if (_mouseStatus) {
+ // Force engine to choose a cursor
+ _mouseStatus = false;
+ _mouseTouching = 1;
+ }
- // If 'pointer_text' field is set, but the 'id' field isn't same is
- // current id, then we don't want this "left over" pointer text
+ // Clear this to reset no-second-click system
+ Logic::_scriptVars[CLICKED_ID] = 0;
- if (_mouseList[_curMouse].pointer_text && _mouseList[_curMouse].id != (int32) Logic::_scriptVars[ID])
- _mouseList[_curMouse].pointer_text = 0;
+ // This is now done outside the OBJECT_HELD check in case it's set to
+ // zero before now!
- // Get id from system variable 'id' which is correct for current object
+ // Unlock the mouse from possible large object lock situtations - see
+ // syphon in rm 3
- _mouseList[_curMouse].id = Logic::_scriptVars[ID];
+ _mouseModeLocked = false;
- // Not using sprite as mask - this is only done from fnRegisterFrame()
+ if (Logic::_scriptVars[OBJECT_HELD]) {
+ // Was dragging something around - need to clear this again
+ Logic::_scriptVars[OBJECT_HELD] = 0;
- _mouseList[_curMouse].anim_resource = 0;
- _mouseList[_curMouse].anim_pc = 0;
+ // And these may also need clearing, just in case
+ _examiningMenuIcon = false;
+ Logic::_scriptVars[COMBINE_BASE] = 0;
- debug(5, "mouse id %d", _mouseList[_curMouse].id);
- _curMouse++;
+ setLuggage(0);
+ }
+
+ // If mouse is over menu area
+ if (_pos.y > 399) {
+ if (_mouseMode != MOUSE_holding) {
+ // VITAL - reset things & rebuild the menu
+ _mouseMode = MOUSE_normal;
+ }
+ setMouse(NORMAL_MOUSE_ID);
+ }
+
+ // Enabled/disabled from console; status printed with on-screen debug
+ // info
+
+ if (_vm->_debugger->_testingSnR) {
+ uint8 black[4] = { 0, 0, 0, 0 };
+ uint8 white[4] = { 255, 255, 255, 0 };
+
+ // Testing logic scripts by simulating instant Save & Restore
+
+ _vm->_screen->setPalette(0, 1, white, RDPAL_INSTANT);
+
+ // Stops all fx & clears the queue - eg. when leaving a room
+ _vm->_sound->clearFxQueue();
+
+ // Trash all object resources so they load in fresh & restart
+ // their logic scripts
+
+ _vm->_resman->killAllObjects(false);
+
+ _vm->_screen->setPalette(0, 1, black, RDPAL_INSTANT);
+ }
+}
+
+void Mouse::refreshInventory() {
+ // Can reset this now
+ Logic::_scriptVars[COMBINE_BASE] = 0;
+
+ // Cause 'object_held' icon to be greyed. The rest are coloured.
+ _examiningMenuIcon = true;
+ buildMenu();
+ _examiningMenuIcon = false;
+}
+
+void Mouse::startConversation() {
+ if (Logic::_scriptVars[TALK_FLAG] == 0) {
+ // See fnChooser & speech scripts
+ Logic::_scriptVars[CHOOSER_COUNT_FLAG] = 0;
+ }
+
+ noHuman();
+}
+
+void Mouse::endConversation() {
+ hideMenu(RDMENU_BOTTOM);
+
+ if (_pos.y > 399) {
+ // Will wait for cursor to move off the bottom menu
+ _mouseMode = MOUSE_holding;
+ }
+
+ // In case DC forgets
+ Logic::_scriptVars[TALK_FLAG] = 0;
}
-void Sword2Engine::monitorPlayerActivity(void) {
+void Mouse::monitorPlayerActivity() {
// if there is at least one mouse event outstanding
- if (checkForMouseEvents()) {
+ if (_vm->checkForMouseEvents()) {
// reset activity delay counter
_playerActivityDelay = 0;
} else {
@@ -1080,4 +1285,33 @@ void Sword2Engine::monitorPlayerActivity(void) {
}
}
+void Mouse::checkPlayerActivity(uint32 seconds) {
+ // Convert seconds to game cycles
+ uint32 threshold = seconds * 12;
+
+ // If the actual delay is at or above the given threshold, reset the
+ // activity delay counter now that we've got a positive check.
+
+ if (_playerActivityDelay >= threshold) {
+ _playerActivityDelay = 0;
+ Logic::_scriptVars[RESULT] = 1;
+ } else
+ Logic::_scriptVars[RESULT] = 0;
+}
+
+void Mouse::pauseGame() {
+ // Make the mouse cursor normal. This is the only place where we are
+ // allowed to clear the luggage this way.
+
+ clearPointerText();
+ setLuggageAnim(NULL, 0);
+ setMouse(0);
+ setMouseTouching(1);
+}
+
+void Mouse::unpauseGame() {
+ if (Logic::_scriptVars[OBJECT_HELD] && _realLuggageItem)
+ setLuggage(_realLuggageItem);
+}
+
} // End of namespace Sword2