aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--queen/command.cpp356
-rw-r--r--queen/command.h7
-rw-r--r--queen/logic.cpp29
-rw-r--r--queen/logic.h22
4 files changed, 185 insertions, 229 deletions
diff --git a/queen/command.cpp b/queen/command.cpp
index 80ada1b27c..727dd6b9e3 100644
--- a/queen/command.cpp
+++ b/queen/command.cpp
@@ -32,7 +32,6 @@
namespace Queen {
-
void CmdText::clear() {
memset(_command, 0, sizeof(_command));
@@ -50,7 +49,7 @@ void CmdText::displayTemp(uint8 color, bool locked, const Verb& v, const char *n
char temp[MAX_COMMAND_LEN];
if (locked) {
- sprintf(temp, "%s%s", _logic->lockedVerbPrefix(), v.name());
+ sprintf(temp, "%s%s", _logic->joeResponse(39), v.name());
}
else {
strcpy(temp, v.name());
@@ -145,44 +144,32 @@ void Command::clear(bool clearTexts) {
}
+// FIXME: walk argument is useless (always true), as we don't handle the
+// pinnacle room exactly like the original
void Command::executeCurrentAction(bool walk) {
_logic->entryObj(0);
- const char *obj1Name = NULL;
- const char *obj2Name = NULL;
-
if (_curCmd.commandLevel == 2 && _mouseKey == Input::MOUSE_RBUTTON) {
_mouseKey = Input::MOUSE_LBUTTON;
}
// XXX SUBJ1=SUBJECT[1]; SUBJ2=SUBJECT[2];
- uint16 objMax = _logic->currentRoomObjMax();
- uint16 roomData = _logic->currentRoomData();
-
if (_mouseKey == Input::MOUSE_RBUTTON && _curCmd.subject1 != 0) {
// check to see if selecting default command for object/item
if (_curCmd.subject1 > 0) {
- // an object
- int16 i = _curCmd.subject1;
- if (_curCmd.noun > objMax) {
- int16 aObj = _logic->currentRoomArea(_curCmd.noun - objMax)->object;
- int16 aObjName = _logic->objectData(aObj)->name;
- if (aObjName > 0) {
- _curCmd.noun = objMax;
- i = aObj;
- }
- }
- ObjectData *od = _logic->objectData(ABS(i));
- obj1Name = _logic->objectName(od->name);
- if (_curCmd.noun == 0 || _curCmd.noun > objMax || _logic->objectData(i)->name <= 0) {
+ int16 i = _logic->findObjectGlobalNumber(_curCmd.noun);
+
+ if (_curCmd.noun == 0 ||
+ _curCmd.noun > _logic->currentRoomObjMax() ||
+ _logic->objectData(i)->name <= 0) {
cleanupCurrentAction();
return;
}
- uint16 obj = roomData + _curCmd.noun;
+ uint16 obj = _logic->currentRoomData() + _curCmd.noun;
_curCmd.verb = findDefault(obj, false);
if (_curCmd.verb.isNone()) {
// no match made, so command not yet completed, redefine as WALK_TO
@@ -195,11 +182,6 @@ void Command::executeCurrentAction(bool walk) {
}
_cmdText.addObject(_logic->objectName(_logic->objectData(obj)->name));
}
- else {
- // an item
- int16 name = _logic->itemData(ABS(_curCmd.subject1))->name;
- obj1Name = _logic->objectName(name);
- }
}
// make sure that command is always highlighted when actioned!
@@ -210,21 +192,16 @@ void Command::executeCurrentAction(bool walk) {
// XXX SUBJECT[2]=0;
- // get objects names
- obj1Name = _logic->objectOrItemName(_curCmd.subject1);
- obj2Name = _logic->objectOrItemName(_curCmd.subject2);
-
- if (handleBadCommand(walk)) {
+ if (handleDefaultCommand(walk)) {
cleanupCurrentAction();
return;
}
- uint16 i;
-
// get the commands associated with object/item
uint16 comMax = 0;
uint16 matchingCmds[MAX_MATCHING_CMDS];
CmdListData *cmdList = &_cmdList[1];
+ uint16 i;
for (i = 1; i <= _numCmdList; ++i, ++cmdList) {
if (cmdList->match(_selCmd.action, _curCmd.subject1, _curCmd.subject2)) {
matchingCmds[comMax] = i;
@@ -260,18 +237,7 @@ void Command::executeCurrentAction(bool walk) {
if (cond == -1 && i == comMax) {
// only exit on a condition fail if at last command
// Joe hasnt spoken, so do normal LOOK command
- if (_selCmd.action.value() == VERB_LOOK_AT) {
- // Look At, do standard look at routine
- look();
- }
- else {
- if (com->song < 0) {
- _sound->playSong(-com->song);
- }
- clear(true);
- }
- cleanupCurrentAction();
- return;
+ break;
}
else if (cond == -2 && i == comMax) {
// only exit on a condition fail if at last command
@@ -281,159 +247,23 @@ void Command::executeCurrentAction(bool walk) {
}
else if (cond >= 0) {
// we've had a successful Gamestate check, so we must now exit
+ executeCommand(comId, cond);
break;
}
}
- debug(0, "Command::executeCurrentAction() - cond = %X, com = %X", cond, comId);
-
- if (com->setAreas) {
- setAreas(comId);
- }
-
- // Don't grab if action is TALK or WALK
- if (_selCmd.action.value() != VERB_TALK_TO && _selCmd.action.value() != VERB_WALK_TO) {
- if (_curCmd.subject1 > 0) {
- _logic->joeGrab(_logic->objectData(_curCmd.subject1)->state, 0);
- }
- if (_curCmd.subject2 > 0) {
- _logic->joeGrab(_logic->objectData(_curCmd.subject2)->state, 0);
- }
- }
-
- bool cutDone = false;
- if (cond > 0) {
- // FIXME: this stuff must be seriously re-designed !
-
- // CR 2 - 7/3/95, Because we may be calling a cutaway triggered from walking
- // to the pinnacle (which connects to Map room 7), we'll be caught in the
- // R_MAP routine until we select a location and then call this very procedure
- // again - the result being that COM will be reset. So to avoid that, we'll
- // keep a copy of COM until we return from the recursive call...
- // Otherwise, all remaining commands will be wiped and not carried out!
- uint16 comTempId = comId;
- CmdListData *comTemp = com;
-
- const char *desc = _logic->objectTextualDescription(cond);
- if (executeIfCutaway(desc)) {
- cond = 0;
- cutDone = true;
- }
-
- comId = comTempId;
- com = comTemp;
-
- // check for dialogs before updating Objects
- if (executeIfDialog(desc)) {
- cond = 0;
- }
- }
-
- int16 oldImage = 0;
- if (_curCmd.subject1 > 0) {
- // an object (not an item)
- oldImage = _logic->objectData(_curCmd.subject1)->image;
- }
-
- if (com->setObjects) {
- setObjects(comId);
- }
- if (com->setItems) {
- setItems(comId);
- }
-
- if (com->imageOrder != 0) {
- ObjectData* od = _logic->objectData(_curCmd.subject1);
- // we must update the graphic image of the object
- if (com->imageOrder < 0) {
- // instead of setting to -1 or -2, flag as negative
- if (od->image > 0) {
- // make sure that object is not already updated
- od->image = -(od->image + 10);
- }
- }
- else {
- od->image = com->imageOrder;
- }
- _logic->roomRefreshObject(_curCmd.subject1);
- }
- else {
- // this object is not being updated by command list, see if
- // it has another image copied to it
- if (_curCmd.subject1 > 0) {
- // an object (not an item)
- if (_logic->objectData(_curCmd.subject1)->image != oldImage) {
- _logic->roomRefreshObject(_curCmd.subject1);
- }
- }
- }
-
- // don't play music on an OPEN/CLOSE command - in case the command fails
- if (_selCmd.action.value() != VERB_OPEN && _selCmd.action.value() != VERB_CLOSE) {
- // only play song if it's a PLAY BEFORE type
- if (com->song > 0) {
- _sound->playSong(com->song);
- }
- }
-
- // do a special hardcoded section
- // l.419-452 execute.c
- switch (com->specialSection) {
- case 1:
- _logic->useJournal();
- return;
- case 2:
- _logic->joeUseDress(true);
- break;
- case 3:
- _logic->joeUseClothes(true);
- break;
- case 4:
- _logic->joeUseUnderwear();
- break;
- }
-
- changeObjectState(_selCmd.action, _curCmd.subject1, com->song, cutDone);
-
- if (_selCmd.action.value() == VERB_TALK_TO && cond > 0) {
- if (executeIfDialog(_logic->objectTextualDescription(cond))) {
- cleanupCurrentAction();
- return;
- }
- }
-
-// EXECUTE_EXIT1:
- if (cond > 0) {
- const char *desc = _logic->objectTextualDescription(cond);
- // Joe needs to say something as a result of a Gamestate
- // check first to see if it is a cutaway scene!
- if (executeIfCutaway(desc)) {
- }
- else if (executeIfDialog(desc)) {
- cleanupCurrentAction();
- return;
- }
- else {
- _logic->joeSpeak(cond, true);
- }
+ if (_selCmd.action.value() == VERB_LOOK_AT) {
+ // Look At, do standard look at routine
+ look();
}
else {
- // we've failed commands with nothing to say
- if (_selCmd.action.value() == VERB_LOOK_AT) {
- // Look At, do standard look at routine
- look();
- cleanupCurrentAction();
- return;
+ // only play song if it's a PLAY AFTER type
+ if (com->song < 0) {
+ _sound->playSong(-com->song);
}
+ clear(true);
}
-
- // only play song if it's a PLAY AFTER type
- if (com->song < 0) {
- _sound->playSong(-com->song);
- }
-
- clear(true);
cleanupCurrentAction();
}
@@ -528,6 +358,128 @@ void Command::readCommandsFrom(byte *&ptr) {
}
+void Command::executeCommand(uint16 comId, int16 condResult) {
+
+ // execute.c l.313-452
+ debug(0, "Command::executeCommand() - cond = %X, com = %X", condResult, comId);
+
+ CmdListData *com = &_cmdList[comId];
+
+ if (com->setAreas) {
+ setAreas(comId);
+ }
+
+ // Don't grab if action is TALK or WALK
+ if (_selCmd.action.value() != VERB_TALK_TO && _selCmd.action.value() != VERB_WALK_TO) {
+ if (_curCmd.subject1 > 0) {
+ _logic->joeGrab(_logic->objectData(_curCmd.subject1)->state, 0);
+ }
+ if (_curCmd.subject2 > 0) {
+ _logic->joeGrab(_logic->objectData(_curCmd.subject2)->state, 0);
+ }
+ }
+
+ bool cutDone = false;
+ if (condResult > 0) {
+ // as we don't handle the pinnacle room exactly like the original,
+ // the hack described on l.334-339 in execute.c became useless
+
+ // check for cutaway/dialogs before updating Objects
+ const char *desc = _logic->objectTextualDescription(condResult);
+ if (executeIfCutaway(desc)) {
+ condResult = 0;
+ cutDone = true;
+ }
+ else if (executeIfDialog(desc)) {
+ condResult = 0;
+ }
+ }
+
+ int16 oldImage = 0;
+ if (_curCmd.subject1 > 0) {
+ // an object (not an item)
+ oldImage = _logic->objectData(_curCmd.subject1)->image;
+ }
+
+ if (com->setObjects) {
+ setObjects(comId);
+ }
+
+ if (com->setItems) {
+ setItems(comId);
+ }
+
+ if (com->imageOrder != 0) {
+ ObjectData *od = _logic->objectData(_curCmd.subject1);
+ // we must update the graphic image of the object
+ if (com->imageOrder < 0) {
+ // instead of setting to -1 or -2, flag as negative
+ if (od->image > 0) {
+ // make sure that object is not already updated
+ od->image = -(od->image + 10);
+ }
+ }
+ else {
+ od->image = com->imageOrder;
+ }
+ _logic->roomRefreshObject(_curCmd.subject1);
+ }
+ else {
+ // this object is not being updated by command list, see if
+ // it has another image copied to it
+ if (_curCmd.subject1 > 0) {
+ // an object (not an item)
+ if (_logic->objectData(_curCmd.subject1)->image != oldImage) {
+ _logic->roomRefreshObject(_curCmd.subject1);
+ }
+ }
+ }
+
+ // don't play music on an OPEN/CLOSE command - in case the command fails
+ if (_selCmd.action.value() != VERB_OPEN && _selCmd.action.value() != VERB_CLOSE) {
+ // only play song if it's a PLAY BEFORE type
+ if (com->song > 0) {
+ _sound->playSong(com->song);
+ }
+ }
+
+ // do a special hardcoded section
+ // l.419-452 execute.c
+ switch (com->specialSection) {
+ case 1:
+ _logic->useJournal();
+ return;
+ case 2:
+ _logic->joeUseDress(true);
+ break;
+ case 3:
+ _logic->joeUseClothes(true);
+ break;
+ case 4:
+ _logic->joeUseUnderwear();
+ break;
+ }
+
+ changeObjectState(_selCmd.action, _curCmd.subject1, com->song, cutDone);
+
+ // execute.c l.533-548
+ // FIXME: useless test, as .dog has already been played
+ // if (_selCmd.action.value() == VERB_TALK_TO && cond > 0) {
+ // if (executeIfDialog(_logic->objectTextualDescription(cond))) {
+ // cleanupCurrentAction();
+ // return;
+ // }
+ // }
+
+ // execute.c l.550-589
+ // FIXME: the EXECUTE_EXIT1 stuff can be omitted as it is
+ // more or less redundant code
+ if (condResult > 0) {
+ _logic->joeSpeak(condResult, true);
+ }
+}
+
+
int16 Command::makeJoeWalkTo(int16 x, int16 y, int16 objNum, const Verb &v, bool mustWalk) {
// Check to see if object is actually an exit to another
@@ -570,7 +522,10 @@ int16 Command::makeJoeWalkTo(int16 x, int16 y, int16 objNum, const Verb &v, bool
}
else {
p = _walk->moveJoe(facing, x, y, false); // XXX inCutaway parameter
- // XXX if(P != 0) P = FIND_VERB
+ if (p != 0) {
+ _logic->newRoom(0); // cancel makeJoeWalkTo, that should be equivalent to cr10 fix
+ // XXX if(P != 0) P = FIND_VERB
+ }
}
}
return p;
@@ -588,7 +543,6 @@ void Command::grabCurrentSelection() {
_selPosX += _logic->display()->horizontalScroll();
- debug(0, "Command::grabCurrentSelection() - _curCmd.noun = %d, _curCmd.verb = %d, objMax=%d", _curCmd.noun, _curCmd.verb.value(), _logic->currentRoomObjMax());
if (_curCmd.verb.isAction()) {
grabSelectedVerb();
}
@@ -600,7 +554,6 @@ void Command::grabCurrentSelection() {
}
else if (_selPosY < ROOM_ZONE_HEIGHT && _curCmd.verb.isNone()) {
// select without a command, do a WALK
- _logic->newRoom(0); // cancel makeJoeWalkTo, that should be equivalent to cr10 fix
clear(true);
_logic->joeWalk(JWM_EXECUTE);
}
@@ -644,6 +597,7 @@ void Command::grabSelectedObject(int16 objNum, uint16 objState, uint16 objName)
if (_parse) {
_curCmd.verb = Verb(VERB_NONE);
+ //_logic->newRoom(0);
_logic->joeWalk(JWM_EXECUTE);
_selCmd.action = _curCmd.action;
_curCmd.action = Verb(VERB_NONE);
@@ -744,10 +698,11 @@ void Command::grabSelectedNoun() {
uint16 objNum = _logic->currentRoomData() + _curCmd.noun;
int16 objName = _logic->objectData(objNum)->name;
- if (objName < 0) {
+ if (objName <= 0) {
// selected a turned off object, so just walk
- _curCmd.noun = 0;
clear(true);
+ _curCmd.noun = 0;
+ //_logic->newRoom(0);
_logic->joeWalk(JWM_EXECUTE);
return;
}
@@ -808,6 +763,8 @@ void Command::grabSelectedNoun() {
}
_selCmd.noun = 0;
+ // XXX PARSE=1;
+ // XXX if((ACTION==6 || ACTION==5) && CLEVEL==1) PARSE=0;
grabSelectedObject(objNum, _logic->objectData(objNum)->state, objName);
}
@@ -886,7 +843,7 @@ bool Command::executeIfDialog(const char *description) {
}
-bool Command::handleBadCommand(bool walk) {
+bool Command::handleDefaultCommand(bool walk) {
// l.96-141 execute.c
uint16 objMax = _logic->currentRoomObjMax();
@@ -905,7 +862,7 @@ bool Command::handleBadCommand(bool walk) {
if (_curCmd.subject1 > 0 && _logic->objectData(_curCmd.subject1)->name <= 0) {
return true;
}
- if (_selCmd.action.value() == VERB_GIVE &&
+ if (// _selCmd.action.value() == VERB_GIVE && // can be TALK_TO !
_curCmd.subject2 > 0 && _logic->objectData(_curCmd.subject2)->name <= 0) {
return true;
}
@@ -966,8 +923,6 @@ void Command::executeStandardStuff(const Verb& action, int16 subj1, int16 subj2)
_logic->joeSpeak(2);
break;
- case 4: // weird, isn't it ? l.193 execute.c
- warning("Command::executeStandardStuff() - Use of verb 4");
case VERB_MOVE:
// 'I can't move it'
if (subj1 > 0) {
@@ -1153,6 +1108,7 @@ void Command::alterDefault(const Verb& def, bool itemType) {
void Command::openOrCloseAssociatedObject(const Verb& action, int16 otherObj) {
+ warning("using Command::openOrCloseAssociatedObject()");
CmdListData *cmdList = &_cmdList[1];
uint16 com = 0;
uint16 i;
@@ -1623,4 +1579,4 @@ void Command::lookCurrentIcon() {
}
}
-}
+} // End of namespace Queen
diff --git a/queen/command.h b/queen/command.h
index 0b7f29e61a..24d24a5175 100644
--- a/queen/command.h
+++ b/queen/command.h
@@ -66,7 +66,6 @@ struct CurrentCmdState {
Verb action;
int16 oldNoun;
int16 noun;
- //! current level of the command (max=2 for GIVE and USE verbs)
int commandLevel;
int16 subject1;
int16 subject2;
@@ -77,7 +76,6 @@ struct SelectedCmdState {
void init();
- //! locked verb (using 2nd mouse button)
Verb defaultVerb;
Verb action;
int16 noun;
@@ -108,8 +106,11 @@ public:
MAX_MATCHING_CMDS = 50
};
+
private:
+ void executeCommand(uint16 comId, int16 condResult);
+
int16 makeJoeWalkTo(int16 x, int16 y, int16 objNum, const Verb &v, bool mustWalk);
void grabCurrentSelection();
@@ -121,7 +122,7 @@ private:
bool executeIfCutaway(const char *description);
bool executeIfDialog(const char *description);
- bool handleBadCommand(bool walk);
+ bool handleDefaultCommand(bool walk);
void executeStandardStuff(const Verb& action, int16 subj1, int16 subj2);
void changeObjectState(const Verb& action, int16 obj, int16 song, bool cutDone);
void cleanupCurrentAction();
diff --git a/queen/logic.cpp b/queen/logic.cpp
index 03b98e75c2..0396f662f4 100644
--- a/queen/logic.cpp
+++ b/queen/logic.cpp
@@ -399,7 +399,7 @@ void Logic::initialise() {
}
-ObjectData* Logic::objectData(int index) {
+ObjectData* Logic::objectData(int index) const {
index = abs(index); // cyx: is that really necessary ?
if (index <= _numObjects)
return &_objectData[index];
@@ -407,19 +407,23 @@ ObjectData* Logic::objectData(int index) {
error("[Logic::objectData] Invalid object data index: %i", index);
}
-uint16 Logic::roomData(int room) {
+uint16 Logic::roomData(int room) const {
return _roomData[room];
}
-uint16 Logic::objMax(int room) {
+uint16 Logic::objMax(int room) const {
return _objMax[room];
}
-Area *Logic::area(int room, int num) {
+GraphicData *Logic::graphicData(int index) const {
+ return &_graphicData[index];
+}
+
+Area *Logic::area(int room, int num) const {
return &_area[room][num];
}
-Area *Logic::currentRoomArea(int num) {
+Area *Logic::currentRoomArea(int num) const {
if (num == 0 || num > _areaMax[_currentRoom]) {
error("Logic::currentRoomArea() - Bad area number = %d (max = %d), currentRoom = %d", num, _areaMax[_currentRoom], _currentRoom);
}
@@ -427,26 +431,22 @@ Area *Logic::currentRoomArea(int num) {
return &_area[_currentRoom][num];
}
-uint16 Logic::areaMax(int room) {
+uint16 Logic::areaMax(int room) const {
return _areaMax[room];
}
-uint16 Logic::currentRoomAreaMax() {
+uint16 Logic::currentRoomAreaMax() const {
return _areaMax[_currentRoom];
}
-uint16 Logic::walkOffCount() {
+uint16 Logic::walkOffCount() const {
return _numWalkOffs;
}
-WalkOffData *Logic::walkOffData(int index) {
+WalkOffData *Logic::walkOffData(int index) const {
return &_walkOffData[index];
}
-GraphicData *Logic::graphicData(int index) {
- return &_graphicData[index];
-}
-
uint16 Logic::findBob(uint16 obj) {
uint16 i;
@@ -1962,10 +1962,11 @@ uint16 Logic::findObjectRoomNumber(uint16 zoneNum) const {
// l.316-327 select.c
uint16 noun = zoneNum;
uint16 objectMax = _objMax[_currentRoom];
+ debug(0, "Logic::findObjectRoomNumber(%X, %X)", zoneNum, objectMax);
if (zoneNum > objectMax) {
// this is an area box, check for associated object
uint16 obj = _area[_currentRoom][zoneNum - objectMax].object;
- if (obj != 0 && _objectData[obj].name != 0) {
+ if (obj != 0 && objectData(obj)->name != 0) {
// there is an object, get its number
noun = obj - _roomData[_currentRoom];
}
diff --git a/queen/logic.h b/queen/logic.h
index 244eac143d..bd184f0915 100644
--- a/queen/logic.h
+++ b/queen/logic.h
@@ -143,10 +143,10 @@ public:
error("Invalid room number: %i", room);
}
- ObjectData *objectData(int index);
- uint16 roomData(int room);
- uint16 objMax(int room);
- GraphicData *graphicData(int index);
+ ObjectData *objectData(int index) const;
+ uint16 roomData(int room) const;
+ uint16 objMax(int room) const;
+ GraphicData *graphicData(int index) const;
ItemData *itemData(int index) const { return &_itemData[index]; }
uint16 itemDataCount() const { return _numItems; }
@@ -155,12 +155,12 @@ public:
uint16 objectForPerson(uint16 bobnum) const; // OBJ_PERSON
WalkOffData *walkOffPointForObject(uint16 obj) const;
- Area *area(int room, int num);
- Area *currentRoomArea(int num);
- uint16 areaMax(int room);
- uint16 currentRoomAreaMax();
- uint16 walkOffCount();
- WalkOffData *walkOffData(int index);
+ Area *area(int room, int num) const;
+ Area *currentRoomArea(int num) const;
+ uint16 areaMax(int room) const;
+ uint16 currentRoomAreaMax() const;
+ uint16 walkOffCount() const;
+ WalkOffData *walkOffData(int index) const;
uint16 currentRoomObjMax() const { return _objMax[_currentRoom]; }
uint16 currentRoomData() const { return _roomData[_currentRoom]; }
ObjectDescription *objectDescription(uint16 objNum) const { return &_objectDescription[objNum]; }
@@ -272,8 +272,6 @@ public:
uint16 findObjectRoomNumber(uint16 zoneNum) const;
uint16 findObjectGlobalNumber(uint16 zoneNum) const;
- const char *lockedVerbPrefix() const { return _joeResponse[39]; }
-
void inventorySetup();
uint16 findInventoryItem(int invSlot) const;
void inventoryRefresh();