void EMICostume::playChoreLooping(int num, uint msecs) { // FIXME: Original EMI can play multiple instances of a chore at the same time. EMIChore *chore = static_cast<EMIChore *>(_chores[num]); if (chore->isWearChore()) { setWearChore(chore); } Costume::playChoreLooping(num, msecs); }
void EMICostume::saveState(SaveGame *state) const { Costume::saveState(state); for (int i = 0; i < _numChores; ++i) { EMIChore *chore = (EMIChore *)_chores[i]; state->writeLESint32(chore->getId()); } state->writeLESint32(_wearChore ? _wearChore->getChoreId() : -1); }
EMIModel *EMICostume::getEMIModel(int num) const { if (num >= _numChores) { return nullptr; } EMIChore *chore = static_cast<EMIChore *>(_chores[num]); if (chore == nullptr) { return nullptr; } EMIMeshComponent *mesh = chore->getMesh(); if (mesh == nullptr) { return nullptr; } return mesh->_obj; }
bool EMICostume::restoreState(SaveGame *state) { bool ret = Costume::restoreState(state); if (ret) { if (state->saveMinorVersion() >= 11) { EMIChore::Pool &pool = EMIChore::getPool(); for (int i = 0; i < _numChores; ++i) { EMIChore *chore = (EMIChore *)_chores[i]; int id = state->readLESint32(); pool.removeObject(chore->getId()); EMIChore* oldChore = pool.getObject(id); if (oldChore) { pool.removeObject(id); oldChore->setId(chore->getId()); pool.addObject(oldChore); } chore->setId(id); pool.addObject(chore); } } if (state->saveMinorVersion() < 13) { // Used to be active texture IDs for materials. Materials are now // managed by the owner Actor of this Costume. for (uint i = 0; i < _materials.size(); ++i) { state->readLESint32(); } } int id = state->readLESint32(); if (id >= 0) { EMIChore *chore = static_cast<EMIChore *>(_chores[id]); setWearChore(chore); } } return ret; }
void EMICostume::load(Common::SeekableReadStream *data) { Common::Array<Component *> components; _numChores = data->readUint32LE(); _chores = new Chore *[_numChores]; for (int i = 0; i < _numChores; i++) { uint32 nameLength; Component *prevComponent = nullptr; nameLength = data->readUint32LE(); assert(nameLength < 32); char name[32]; data->read(name, nameLength); char f[4]; data->read(f, 4); float length = get_float(f); int numTracks = data->readUint32LE(); if (length == 1000) length = -1.0f; else length *= 1000; EMIChore *chore = new EMIChore(name, i, this, (int)length, numTracks); _chores[i] = chore; for (int k = 0; k < numTracks; k++) { int componentNameLength = data->readUint32LE(); char *componentName = new char[componentNameLength]; data->read(componentName, componentNameLength); data->readUint32LE(); int parentID = data->readUint32LE(); if (parentID == -1 && _prevCostume) { // However, only the first item can actually share the // node hierarchy with the previous costume, so flag // that component so it knows what to do if (i == 0) parentID = -2; prevComponent = _prevCostume->getComponent(0); // Make sure that the component is valid if (!prevComponent->isComponentType('M', 'M', 'D', 'L')) prevComponent = nullptr; } // Actually load the appropriate component Component *component = loadEMIComponent(parentID < 0 ? nullptr : components[parentID], parentID, componentName, prevComponent); if (component) { component->setCostume(this); component->init(); chore->addComponent(component); } components.push_back(component); ChoreTrack &track = chore->_tracks[k]; track.numKeys = data->readUint32LE(); track.keys = new TrackKey[track.numKeys]; track.component = component; track.compID = -1; // -1 means "look at .component" for (int j = 0; j < track.numKeys; j++) { float time, value; char v[8]; data->read(v, 8); time = get_float(v); value = get_float(v + 4); track.keys[j].time = (int)(time * 1000); length = MAX(length, time * 1000); track.keys[j].value = (int)value; } delete[] componentName; } } _numComponents = components.size(); _components = new Component *[_numComponents]; for (int i = 0; i < _numComponents; ++i) { _components[i] = components[i]; } // The wearChore is active by default _isWearChoreActive = true; _head = new EMIHead(this); }
// TODO: Implement, verify, and rename unknown 5th parameter void Lua_V2::PlayActorChore() { lua_Object actorObj = lua_getparam(1); lua_Object choreObj = lua_getparam(2); lua_Object costumeObj = lua_getparam(3); lua_Object modeObj = lua_getparam(4); /* lua_Object paramObj = */ lua_getparam(5); if (!lua_isuserdata(actorObj) || lua_tag(actorObj) != MKTAG('A','C','T','R')) return; Actor *actor = getactor(actorObj); if (!lua_isstring(choreObj) || !lua_isstring(costumeObj)) lua_pushnil(); bool mode = false; // float param = 0.0; if (!lua_isnil(modeObj)) { if (lua_getnumber(modeObj) != 0.0) mode = true; //if (!lua_isnil(paramObj)) // if (lua_isnumber(paramObj)) // param = lua_getnumber(paramObj); } const char *choreName = lua_getstring(choreObj); const char *costumeName = lua_getstring(costumeObj); Costume *costume; // If a new wear chore is set and it uses a different costume than the // current one and neither of them is the shadow costume stop all active // chores and remove the old costume before setting the new one. // // This is necessary, because always the last costume on the stack, even // if it is not active, is returned by getCurrentCostume(). This would // cause an issue if the costumes would have different joints and the lua // code would consider a different costume active than the C code. if (0 == strncmp("wear_", choreName, 5)) { if (0 != strncmp("fx/dumbshadow.cos", costumeName, 17)) { if (actor->getCurrentCostume() != NULL && actor->getCurrentCostume()->getFilename() != "fx/dumbshadow.cos" && actor->getCurrentCostume()->getFilename().compareToIgnoreCase(costumeName) != 0) { actor->stopAllChores(); actor->setRestChore(-1, NULL); actor->setWalkChore(-1, NULL); actor->setTurnChores(-1, -1, NULL); actor->setMumbleChore(-1, NULL); actor->popCostume(); } } } if (!findCostume(costumeObj, actor, &costume)) return; EMIChore *chore = (EMIChore *)costume->getChore(choreName); if (0 == strncmp("wear_", choreName, 5)) { actor->setLastWearChore(costume->getChoreId(choreName), costume); } if (mode) { costume->playChoreLooping(choreName); } else { costume->playChore(choreName); } if (chore) { lua_pushusertag(chore->getId(), MKTAG('C','H','O','R')); } else { lua_pushnil(); } }