Refactored a lot of Character-related code and put it into the Character class.

svn-id: r29025
This commit is contained in:
Nicola Mettifogo 2007-09-22 18:45:43 +00:00
parent 7524244581
commit d7ae40b65d
12 changed files with 207 additions and 182 deletions

View file

@ -392,7 +392,7 @@ void Parallaction_ns::_c_finito(void *parm) {
Common::File stream;
stream.open(_characterName, Common::File::kFileWriteMode);
stream.open(_char.getBaseName(), Common::File::kFileWriteMode);
if (stream.isOpen())
stream.close();

View file

@ -81,7 +81,7 @@ void Debugger::postEnter() {
bool Debugger::Cmd_Location(int argc, const char **argv) {
char *character = _vm->_characterName;
const char *character = _vm->_char.getName();
char *location = _vm->_location._name;
switch (argc) {

View file

@ -142,9 +142,9 @@ uint16 DialogueManager::askPassword() {
g_system->delayMillis(20);
}
if ((!scumm_stricmp(_vm->_characterName, _doughName) && !scumm_strnicmp(password, "1732461", 7)) ||
(!scumm_stricmp(_vm->_characterName, _donnaName) && !scumm_strnicmp(password, "1622", 4)) ||
(!scumm_stricmp(_vm->_characterName, _dinoName) && !scumm_strnicmp(password, "179", 3))) {
if ((!scumm_stricmp(_vm->_char.getBaseName(), _doughName) && !scumm_strnicmp(password, "1732461", 7)) ||
(!scumm_stricmp(_vm->_char.getBaseName(), _donnaName) && !scumm_strnicmp(password, "1622", 4)) ||
(!scumm_stricmp(_vm->_char.getBaseName(), _dinoName) && !scumm_strnicmp(password, "179", 3))) {
break;

View file

@ -400,17 +400,11 @@ Frames* DosDisk_ns::loadTalk(const char *name) {
}
// character talk
char v20[PATH_LEN];
char *v24 = const_cast<char*>(name);
if (IS_MINI_CHARACTER(v24)) {
v24+=4;
}
char v20[30];
if (_engineFlags & kEngineTransformedDonna) {
sprintf(v20, "%stta", v24);
sprintf(v20, "%stta", name);
} else {
sprintf(v20, "%stal", v24);
sprintf(v20, "%stal", name);
}
return loadExternalCnv(v20);
@ -419,19 +413,7 @@ Frames* DosDisk_ns::loadTalk(const char *name) {
Script* DosDisk_ns::loadLocation(const char *name) {
char archivefile[PATH_LEN];
if (IS_MINI_CHARACTER(_vm->_characterName)) {
sprintf(archivefile, "%s%s", _vm->_characterName+4, _languageDir);
} else {
if (IS_DUMMY_CHARACTER(_vm->_characterName)) {
strcpy(archivefile, _languageDir);
} else {
sprintf(archivefile, "%s%s", _vm->_characterName, _languageDir);
}
}
strcat(archivefile, name);
strcat(archivefile, ".loc");
sprintf(archivefile, "%s%s%s.loc", _vm->_char.getBaseName(), _languageDir, name);
debugC(3, kDebugDisk, "DosDisk_ns::loadLocation(%s): trying '%s'", name, archivefile);
@ -462,10 +444,6 @@ Graphics::Surface* DosDisk_ns::loadHead(const char* name) {
char path[PATH_LEN];
if (IS_MINI_CHARACTER(name)) {
name += 4;
}
sprintf(path, "%shead", name);
path[8] = '\0';
@ -487,10 +465,6 @@ Font* DosDisk_ns::loadFont(const char* name) {
Frames* DosDisk_ns::loadObjects(const char *name) {
if (IS_MINI_CHARACTER(name)) {
name += 4;
}
char path[PATH_LEN];
sprintf(path, "%sobj", name);
return loadExternalCnv(path);
@ -1017,10 +991,7 @@ Script* AmigaDisk_ns::loadLocation(const char *name) {
debugC(1, kDebugDisk, "AmigaDisk_ns()::loadLocation '%s'", name);
char path[PATH_LEN];
if (IS_MINI_CHARACTER(_vm->_characterName)) {
sprintf(path, "%s%s%s.loc.pp", _vm->_characterName+4, _languageDir, name);
} else
sprintf(path, "%s%s%s.loc.pp", _vm->_characterName, _languageDir, name);
sprintf(path, "%s%s%s.loc.pp", _vm->_char.getBaseName(), _languageDir, name);
if (!_locArchive.openArchivedFile(path)) {
sprintf(path, "%s%s.loc.pp", _languageDir, name);

View file

@ -179,9 +179,7 @@ DECLARE_INSTRUCTION_OPCODE(move) {
int16 x = inst->_opA.getRValue();
int16 y = inst->_opB.getRValue();
WalkNodeList *v4 = _char._builder.buildPath(x, y);
addJob(kJobWalk, v4, kPriority19 );
_engineFlags |= kEngineWalking;
_char.scheduleWalk(x, y);
}
DECLARE_INSTRUCTION_OPCODE(endscript) {
@ -319,14 +317,7 @@ DECLARE_COMMAND_OPCODE(quit) {
DECLARE_COMMAND_OPCODE(move) {
if ((_char._ani._flags & kFlagsRemove) || (_char._ani._flags & kFlagsActive) == 0) {
return;
}
WalkNodeList *vC = _char._builder.buildPath(_cmdRunCtxt.cmd->u._move.x, _cmdRunCtxt.cmd->u._move.y);
addJob(kJobWalk, vC, kPriority19 );
_engineFlags |= kEngineWalking;
_char.scheduleWalk(_cmdRunCtxt.cmd->u._move.x, _cmdRunCtxt.cmd->u._move.y);
}

View file

@ -178,7 +178,7 @@ void Menu::newGame() {
selectCharacter();
char *v4 = strchr(_vm->_location._name, '.') + 1;
strcpy(_vm->_characterName, v4);
_vm->_char.setName(v4);
return; // start game
}
@ -291,8 +291,7 @@ uint16 Menu::selectGame() {
// The 2 strcpy's below act as workaround to prevent crashes for
// time being.
strcpy(_vm->_location._name, "fogne");
strcpy(_vm->_characterName, "dough");
_vm->_char.setName("dough");
_vm->loadGame();
return 1; // load game

View file

@ -91,7 +91,7 @@ static Job *_jRunScripts = NULL;
Parallaction::Parallaction(OSystem *syst) :
Engine(syst) {
Engine(syst), _char(this) {
// FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what
// needs fixing, or remove it!
@ -170,7 +170,8 @@ int Parallaction::init() {
_backgroundInfo = new BackgroundInfo;
strcpy(_characterName1, "null");
strcpy(_characterName, "dough");
// strcpy(_char._name, "dough");
_char.setName("dough");
memset(_locationNames, 0, NUM_LOCATIONS * 32);
@ -440,11 +441,7 @@ void Parallaction::processInput(InputData *data) {
debugC(2, kDebugInput, "processInput: kEvWalk");
_hoverZone = NULL;
changeCursor(kCursorArrow);
if (_char._ani._flags & kFlagsRemove) break;
if ((_char._ani._flags & kFlagsActive) == 0) break;
WalkNodeList *v4 = _char._builder.buildPath(data->_mousePos.x, data->_mousePos.y);
addJob(kJobWalk, v4, kPriority19);
_engineFlags |= kEngineWalking; // inhibits processing of input until walking is over
_char.scheduleWalk(data->_mousePos.x, data->_mousePos.y);
}
break;
@ -654,26 +651,11 @@ void Parallaction::changeCursor(int32 index) {
void Parallaction::freeCharacter() {
debugC(1, kDebugExec, "freeCharacter()");
if (!IS_DUMMY_CHARACTER(_characterName)) {
if (_objectsNames)
delete _objectsNames;
_objectsNames = NULL;
if (_char._ani._cnv)
delete _char._ani._cnv;
_char._ani._cnv = NULL;
if (_char._talk)
delete _char._talk;
_char._talk = NULL;
delete _char._head;
_char._head = NULL;
if (_char._objs)
delete _char._objs;
_char._objs = NULL;
}
_char.free();
return;
}
@ -1054,11 +1036,137 @@ void Parallaction::freeZones() {
}
const char Character::_prefixMini[] = "mini";
const char Character::_suffixTras[] = "tras";
const char Character::_empty[] = "\0";
Character::Character(Parallaction *vm) : _vm(vm), _builder(&_ani) {
_talk = NULL;
_head = NULL;
_objs = NULL;
_ani._left = 150;
_ani._top = 100;
_ani._z = 10;
_ani._oldPos.x = -1000;
_ani._oldPos.y = -1000;
_ani._frame = 0;
_ani._flags = kFlagsActive | kFlagsNoName;
_ani._type = kZoneYou;
_ani._label._cnv.pixels = NULL;
_ani._label._text = strdup("yourself");
}
void Character::getFoot(Common::Point &foot) {
foot.x = _ani._left + _ani.width() / 2;
foot.y = _ani._top + _ani.height();
}
void Character::setFoot(const Common::Point &foot) {
_ani._left = foot.x - _ani.width() / 2;
_ani._top = foot.y - _ani.height();
}
void Character::scheduleWalk(int16 x, int16 y) {
if ((_ani._flags & kFlagsRemove) || (_ani._flags & kFlagsActive) == 0) {
return;
}
WalkNodeList *list = _builder.buildPath(x, y);
_vm->addJob(kJobWalk, list, kPriority19 );
_engineFlags |= kEngineWalking;
}
void Character::free() {
if (_ani._cnv)
delete _ani._cnv;
if (_talk)
delete _talk;
if (_head)
delete _head;
if (_objs)
delete _objs;
_ani._cnv = NULL;
_talk = NULL;
_head = NULL;
_objs = NULL;
return;
}
// Various ways of detecting character modes used to exist
// inside the engine, so they have been unified in the two
// following macros.
// Mini characters are those used in far away shots, like
// the highway scenery, while Dummy characters are a mere
// workaround to keep the engine happy when showing slides.
// As a sidenote, standard sized characters' names start
// with a lowercase 'd'.
#define IS_MINI_CHARACTER(s) (((s)[0] == 'm'))
#define IS_DUMMY_CHARACTER(s) (((s)[0] == 'D'))
void Character::setName(const char *name) {
const char *begin = name;
const char *end = begin + strlen(name);
_prefix = _empty;
_suffix = _empty;
if (IS_DUMMY_CHARACTER(name)) {
begin = 0;
end = 0;
} else {
char *s = strstr(name, "tras");
if (s) {
_suffix = _suffixTras;
end = s;
}
if (IS_MINI_CHARACTER(name)) {
_prefix = _prefixMini;
begin = name+4;
}
}
memset(_baseName, 0, 30);
strncpy(_baseName, begin, end - begin);
sprintf(_name, "%s%s", _prefix, _baseName);
sprintf(_fullName, "%s%s%s", _prefix, _baseName, _suffix);
}
void Character::transform() {
if (scumm_stricmp("donna", _baseName)) {
error("can't transform character %s", _baseName);
}
if (_suffix) {
_suffix = _empty;
} else {
_suffix = _suffixTras;
}
_engineFlags ^= kEngineTransformedDonna;
setName(_name);
}
const char *Character::getName() const {
return _name;
}
const char *Character::getBaseName() const {
return _baseName;
}
const char *Character::getFullName() const {
return _fullName;
}

View file

@ -175,16 +175,6 @@ extern const char *_minidonnaName;
extern const char *_minidoughName;
extern const char *_minidrkiName;
// Various ways of detecting character modes used to exist
// inside the engine, so they have been unified in the two
// following macros.
// Mini characters are those used in far away shots, like
// the highway scenery, while Dummy characters are a mere
// workaround to keep the engine happy when showing slides.
// As a sidenote, standard sized characters' names start
// with a lowercase 'd'.
#define IS_MINI_CHARACTER(s) (((s)[0] == 'm'))
#define IS_DUMMY_CHARACTER(s) (((s)[0] == 'D'))
void waitUntilLeftClick();
@ -215,41 +205,43 @@ struct Location {
CommandList _escapeCommands;
};
struct Character {
Parallaction *_vm;
Animation _ani;
Graphics::Surface *_head;
Frames *_talk;
Frames *_objs;
PathBuilder _builder;
Character() : _builder(&_ani) {
_talk = NULL;
_head = NULL;
_objs = NULL;
Character(Parallaction *vm);
void getFoot(Common::Point &foot);
void setFoot(const Common::Point &foot);
void scheduleWalk(int16 x, int16 y);
_ani._left = 150;
_ani._top = 100;
_ani._z = 10;
_ani._oldPos.x = -1000;
_ani._oldPos.y = -1000;
_ani._frame = 0;
_ani._flags = kFlagsActive | kFlagsNoName;
_ani._type = kZoneYou;
_ani._label._cnv.pixels = NULL;
_ani._label._text = strdup("yourself");
}
void free();
void getFoot(Common::Point &foot) {
foot.x = _ani._left + _ani.width() / 2;
foot.y = _ani._top + _ani.height();
}
void setFoot(const Common::Point &foot) {
_ani._left = foot.x - _ani.width() / 2;
_ani._top = foot.y - _ani.height();
}
protected:
const char *_prefix;
const char *_suffix;
char _name[30];
char _baseName[30];
char _fullName[30];
static const char _prefixMini[];
static const char _suffixTras[];
static const char _empty[];
public:
void setName(const char *name);
void transform();
const char *getName() const;
const char *getBaseName() const;
const char *getFullName() const;
};
@ -471,7 +463,6 @@ public:
Disk* _disk;
Character _char;
char _characterName[30];
uint32 _localFlags[NUM_LOCATIONS];
char _locationNames[NUM_LOCATIONS][32];

View file

@ -187,7 +187,7 @@ int Parallaction_ns::go() {
_globalTable = _disk->loadTable("global");
_engineFlags &= ~kEngineChangeLocation;
changeCharacter(_characterName);
changeCharacter(_char.getName());
strcpy(_saveData1, _location._name);
parseLocation(_location._name);
@ -272,7 +272,6 @@ void Parallaction_ns::changeLocation(char *location) {
// list is now only [L].{[C]} (see above comment)
if (list.size() == 2) {
changeCharacter(list[1].c_str());
strcpy(_characterName, list[1].c_str());
}
}
@ -331,37 +330,30 @@ void Parallaction_ns::changeLocation(char *location) {
void Parallaction_ns::changeCharacter(const char *name) {
debugC(1, kDebugExec, "changeCharacter(%s)", name);
char baseName[20];
if (IS_MINI_CHARACTER(name)) {
strcpy(baseName, name+4);
} else {
strcpy(baseName, name);
_char.setName(name);
if (!scumm_stricmp(_char.getFullName(), _characterName1)) {
debugC(3, kDebugExec, "changeCharacter: nothing done");
return;
}
char fullName[20];
strcpy(fullName, name);
if (_engineFlags & kEngineTransformedDonna)
strcat(fullName, "tras");
if (scumm_stricmp(fullName, _characterName1)) {
// freeCharacter takes responsibility for checking
// character for sanity before memory is freed
freeCharacter();
Common::String oldArchive = _disk->selectArchive((getFeatures() & GF_LANG_MULT) ? "disk1" : "disk0");
_char._ani._cnv = _disk->loadFrames(fullName);
_char._ani._cnv = _disk->loadFrames(_char.getFullName());
if (!IS_DUMMY_CHARACTER(name)) {
if (_char.getBaseName()[0] != '\0') {
if (getPlatform() == Common::kPlatformAmiga && (getFeatures() & GF_LANG_MULT))
_disk->selectArchive("disk0");
_char._head = _disk->loadHead(baseName);
_char._talk = _disk->loadTalk(baseName);
_char._objs = _disk->loadObjects(baseName);
_objectsNames = _disk->loadTable(baseName);
_char._head = _disk->loadHead(_char.getBaseName());
_char._talk = _disk->loadTalk(_char.getBaseName());
_char._objs = _disk->loadObjects(_char.getBaseName());
_objectsNames = _disk->loadTable(_char.getBaseName());
_soundMan->playCharacterMusic(name);
_soundMan->playCharacterMusic(_char.getBaseName());
if (!(getFeatures() & GF_DEMO))
parseLocation("common");
@ -369,11 +361,10 @@ void Parallaction_ns::changeCharacter(const char *name) {
if (!oldArchive.empty())
_disk->selectArchive(oldArchive);
}
strcpy(_characterName1, fullName);
strcpy(_characterName1, _char.getFullName());
debugC(1, kDebugExec, "changeCharacter() done");
debugC(3, kDebugExec, "changeCharacter: switch completed");
return;
}

View file

@ -312,7 +312,7 @@ DECLARE_LOCATION_PARSER(zeta) {
DECLARE_COMMAND_PARSER(ifchar) {
debugC(7, kDebugParser, "COMMAND_PARSER(ifchar) ");
if (!scumm_stricmp(_characterName, _tokens[1]))
if (!scumm_stricmp(_char.getName(), _tokens[1]))
skip(_locParseCtxt.script, "endif");
}

View file

@ -92,7 +92,9 @@ void Parallaction_ns::doLoadGame(uint16 slot) {
f->readLine(s, 29);
f->readLine(_characterName, 15);
f->readLine(s, 15);
_char.setName(s);
f->readLine(_location._name, 15);
strcat(_location._name, ".");
@ -144,32 +146,11 @@ void Parallaction_ns::doLoadGame(uint16 slot) {
delete f;
_engineFlags &= ~kEngineTransformedDonna;
if (!scumm_stricmp(_characterName, "donnatras")) {
_engineFlags |= kEngineTransformedDonna;
strcpy(_characterName, "donna");
}
if (!scumm_stricmp(_characterName, "minidonnatras")) {
_engineFlags |= kEngineTransformedDonna;
strcpy(_characterName, _minidonnaName);
}
if (IS_MINI_CHARACTER(_characterName)) {
strcpy(filename, _characterName+4);
} else {
strcpy(filename, _characterName);
}
// strcat(filename, ".tab");
// freeTable(_objectsNames);
// initTable(filename, _objectsNames);
// parseLocation("common");
// force reload of character to solve inventory
// bugs, but it's a good maneuver anyway
strcpy(_characterName1, "null");
strcat(_location._name, _characterName);
strcat(_location._name, _char.getName());
_engineFlags |= kEngineChangeLocation;
return;
@ -201,11 +182,7 @@ void Parallaction_ns::doSaveGame(uint16 slot, const char* name) {
f->writeString(s);
f->writeString("\n");
if (_engineFlags & kEngineTransformedDonna) {
sprintf(s, "%stras\n", _characterName);
} else {
sprintf(s, "%s\n", _characterName);
}
sprintf(s, "%s\n", _char.getFullName());
f->writeString(s);
sprintf(s, "%s\n", _saveData1);

View file

@ -257,9 +257,6 @@ void DosSoundMan::playCharacterMusic(const char *character) {
char *name = const_cast<char*>(character);
if (IS_MINI_CHARACTER(name))
name+=4;
if (!scumm_stricmp(name, _dinoName)) {
setMusicFile("dino");
} else
@ -278,7 +275,7 @@ void DosSoundMan::playCharacterMusic(const char *character) {
void DosSoundMan::playLocationMusic(const char *location) {
if (_musicData1 != 0) {
playCharacterMusic(_vm->_characterName);
playCharacterMusic(_vm->_char.getBaseName());
_musicData1 = 0;
debugC(2, kDebugExec, "changeLocation: started character specific music");
}