void BehaviorInfo::initObjectBehavior(GameVar *var, Scene *sc, StaticANIObject *ani) { debug(0, "BehaviorInfo::initObjectBehavior(%s)", transCyrillic((byte *)var->_varName)); clear(); _itemsCount = var->getSubVarsCount(); _counterMax = -1; while (var->_varType == 2) { if (strcmp(var->_value.stringValue, "ROOT")) break; GameVar *v1 = g_fullpipe->getGameLoaderGameVar()->getSubVarByName("BEHAVIOR")->getSubVarByName(ani->getName()); if (v1 == var) return; sc = g_fullpipe->accessScene(ani->_sceneId); clear(); var = v1; _itemsCount = var->getSubVarsCount(); _counterMax = -1; } for (int i = 0; i < _itemsCount; i++) { int maxDelay = 0; _bheItems.push_back(new BehaviorEntry(var->getSubVarByIndex(i), sc, ani, &maxDelay)); if (maxDelay < _counterMax) _counterMax = maxDelay; } }
void BehaviorManager::updateStaticAniBehavior(StaticANIObject *ani, int delay, BehaviorEntry *bhe) { debug(0, "BehaviorManager::updateStaticAniBehavior(%s)", transCyrillic((byte *)ani->_objectName)); MessageQueue *mq = 0; if (bhe->_flags & 1) { uint rnd = g_fullpipe->_rnd->getRandomNumber(32767); uint runPercent = 0; for (int i = 0; i < bhe->_itemsCount; i++) { if (!(bhe->_items[i]->_flags & 1) && bhe->_items[i]->_percent) { if ((rnd >= runPercent && rnd <= runPercent + bhe->_items[i]->_percent) || i == bhe->_itemsCount - 1) { mq = new MessageQueue(bhe->_items[i]->_messageQueue, 0, 1); break; } runPercent += bhe->_items[i]->_percent; } } } else { for (int i = 0; i < bhe->_itemsCount; i++) { if (!(bhe->_items[i]->_flags & 1) && delay >= bhe->_items[i]->_delay) { if (bhe->_items[i]->_percent) { if (g_fullpipe->_rnd->getRandomNumber(32767) <= bhe->_items[i]->_percent) { mq = new MessageQueue(bhe->_items[i]->_messageQueue, 0, 1); break; } } } } } if (mq) { mq->replaceKeyCode(-1, ani->_okeyCode); mq->chain(ani); } }
Common::String MfcArchive::readPascalString(bool twoByte) { char *tmp; int len; Common::String result; if (twoByte) len = readUint16LE(); else len = readByte(); tmp = (char *)calloc(len + 1, 1); read(tmp, len); result = tmp; free(tmp); debugC(9, kDebugLoading, "readPascalString: %d <%s>", len, transCyrillic(result)); return result; }
bool GameVar::load(MfcArchive &file) { _varName = file.readPascalString(); _varType = file.readUint32LE(); debugCN(6, kDebugLoading, "[%03d] ", file.getLevel()); for (int i = 0; i < file.getLevel(); i++) debugCN(6, kDebugLoading, " "); debugCN(6, kDebugLoading, "<%s>: ", transCyrillic(_varName)); switch (_varType) { case 0: _value.intValue = file.readUint32LE(); debugC(6, kDebugLoading, "d --> %d", _value.intValue); break; case 1: _value.intValue = file.readUint32LE(); // FIXME debugC(6, kDebugLoading, "f --> %f", _value.floatValue); break; case 2: { Common::String str = file.readPascalString(); _value.stringValue = (char *)calloc(str.size() + 1, 1); Common::strlcpy(_value.stringValue, str.c_str(), str.size() + 1); debugC(6, kDebugLoading, "s --> %s", _value.stringValue); } break; default: error("Unknown var type: %d (0x%x)", _varType, _varType); } file.incLevel(); _parentVarObj = file.readClass<GameVar>(); _prevVarObj = file.readClass<GameVar>(); _nextVarObj = file.readClass<GameVar>(); _field_14 = file.readClass<GameVar>(); _subVars = file.readClass<GameVar>(); file.decLevel(); return true; }
void BehaviorInfo::initAmbientBehavior(GameVar *var, Scene *sc) { debug(0, "BehaviorInfo::initAmbientBehavior(%s)", transCyrillic((byte *)var->_varName)); clear(); _itemsCount = 1; _counterMax = -1; BehaviorEntry *bi = new BehaviorEntry(); _bheItems.push_back(bi); bi->_itemsCount = var->getSubVarsCount(); bi->_items = (BehaviorEntryInfo**)calloc(bi->_itemsCount, sizeof(BehaviorEntryInfo *)); for (int i = 0; i < bi->_itemsCount; i++) { int delay; bi->_items[i] = new BehaviorEntryInfo(var->getSubVarByIndex(i), sc, &delay); if (bi->_items[i]->_delay <_counterMax) _counterMax = bi->_items[i]->_delay; } }
bool GameVar::load(MfcArchive &file) { _varName = file.readPascalString(); _varType = file.readUint32LE(); debugN(6, "[%03d] ", file.getLevel()); for (int i = 0; i < file.getLevel(); i++) debugN(6, " "); debugN(6, "<%s>: ", transCyrillic((byte *)_varName)); switch (_varType) { case 0: _value.intValue = file.readUint32LE(); debug(6, "d --> %d", _value.intValue); break; case 1: _value.intValue = file.readUint32LE(); // FIXME debug(6, "f --> %f", _value.floatValue); break; case 2: _value.stringValue = file.readPascalString(); debug(6, "s --> %s", _value.stringValue); break; default: error("Unknown var type: %d (0x%x)", _varType, _varType); } file.incLevel(); _parentVarObj = (GameVar *)file.readClass(); _prevVarObj = (GameVar *)file.readClass(); _nextVarObj = (GameVar *)file.readClass(); _field_14 = (GameVar *)file.readClass(); _subVars = (GameVar *)file.readClass(); file.decLevel(); return true; }
bool InteractionController::handleInteraction(StaticANIObject *subj, GameObject *obj, int invId) { if (subj) { if (!subj->isIdle() || (subj->_flags & 0x100)) return false; } if (!_interactions.size()) return false; Interaction *inter = 0; Interaction *previnter = 0; int dur = 0; int mindur = 0xFFFF; MessageQueue *mq; ExCommand *ex; for (InteractionList::iterator i = _interactions.begin(); i != _interactions.end(); ++i) { Interaction *cinter = *i; if (!cinter->canInteract(subj, obj, invId)) continue; if ((inter || cinter->_objectId2) && (!obj || cinter->_objectId3 != obj->_id)) { if (cinter->_messageQueue) cinter->_messageQueue->calcDuration(subj); debugC(5, kDebugInteractions, "Interaction: %s", transCyrillic(cinter->_actionName)); PicAniInfo aniInfo; obj->getPicAniInfo(aniInfo); if (cinter->_staticsId1 && obj->_objtype == kObjTypeStaticANIObject) { StaticANIObject *ani = static_cast<StaticANIObject *>(obj); ani->_messageQueueId = 0; ani->changeStatics2(cinter->_staticsId1); } int xpos = cinter->_xOffs + obj->_ox; int ypos = cinter->_yOffs + obj->_oy; obj->setPicAniInfo(aniInfo); if (abs(xpos - subj->_ox) > 1 || abs(ypos - subj->_oy) > 1) { debugC(0, kDebugPathfinding, "Calling makeQueue() at [%d, %d]", xpos, ypos); mq = getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->makeQueue(subj, xpos, ypos, 1, cinter->_staticsId2); if (mq) { dur = mq->calcDuration(subj); delete mq; } else { dur = 0x10000; } inter = previnter; } else { dur = 0; } if (dur < mindur) { inter = cinter; mindur = dur; previnter = cinter; } } else { inter = cinter; break; } } if (!inter) return false; if (!inter->_objectId2) { if (obj->_objtype == kObjTypeStaticANIObject) { StaticANIObject *ani = static_cast<StaticANIObject *>(obj); if (inter->_flags & 1) { if (!ani->isIdle()) return false; if (ani->_flags & 0x100) return false; } else if (inter->_staticsId1 != 0) { if (ani->_movement || ani->_statics == 0 || ani->_statics->_staticsId != inter->_staticsId1) { mq = ani->changeStatics1(inter->_staticsId1); if (!mq) return false; ex = new ExCommand((subj ? subj->_id : 0), 55, 0, 0, 0, 0, 1, 0, 0, 0); ex->_x = obj->_id; ex->_y = obj->_odelay; ex->_param = subj ? subj->_odelay : 0; ex->_excFlags = 3; ex->_z = (obj->_objtype != kObjTypePictureObject); ex->_field_20 = invId; mq->addExCommandToEnd(ex); if (mq->_isFinished) { mq->_isFinished = 0; ani->queueMessageQueue(mq); } return true; } else { if (ani->getMessageQueue()) ani->queueMessageQueue(0); } } } if (inter->_messageQueue) { mq = new MessageQueue(inter->_messageQueue, 0, 1); mq->changeParam28ForObjectId(obj->_id, -1, obj->_odelay); if (!mq->chain(0)) return false; } return true; } if (obj && !subj) return true; if (!obj || inter->_objectId3 == obj->_id) { if (subj) { if (inter->_messageQueue) { if (subj->isIdle()) { mq = new MessageQueue(inter->_messageQueue, 0, 1); if (!mq->chain(subj)) { delete mq; return false; } } } } return true; } if (inter->isOverlapping(subj, obj)) { if (obj->_objtype == kObjTypeStaticANIObject) { StaticANIObject *ani = static_cast<StaticANIObject *>(obj); ani->queueMessageQueue(0); if (inter->_staticsId1) ani->changeStatics2(inter->_staticsId1); if (!(inter->_flags & 0x10000)) obj->_flags |= 0x80; } if (!inter->_messageQueue) return false; subj->setOXY(inter->_xOffs + obj->_ox, inter->_yOffs + obj->_oy); mq = new MessageQueue(inter->_messageQueue, 0, 1); mq->changeParam28ForObjectId(obj->_id, -1, obj->_odelay); mq->_flags |= 1; if (!(inter->_flags & 0x10000)) { ex = new ExCommand(obj->_id, 34, 0x80, 0, 0, 0, 1, 0, 0, 0); ex->_param = obj->_odelay; ex->_z = 0x80; ex->_messageNum = 0; ex->_excFlags = 3; mq->addExCommandToEnd(ex); } ex = new ExCommand(obj->_id, 34, 0x100, 0, 0, 0, 1, 0, 0, 0); ex->_param = obj->_odelay; ex->_z = 0x100; ex->_messageNum = 0; ex->_excFlags = 3; mq->addExCommandToEnd(ex); ex = new ExCommand(subj->_id, 34, 0x100, 0, 0, 0, 1, 0, 0, 0); ex->_param = subj->_odelay; ex->_z = 0x100; ex->_messageNum = 0; ex->_excFlags = 3; mq->addExCommandToEnd(ex); ex = new ExCommand(subj->_id, 17, 0x40, 0, 0, 0, 1, 0, 0, 0); ex->_excFlags |= 3; ex->_param = 0; mq->addExCommandToEnd(ex); if (!mq->chain(subj)) { delete mq; return false; } subj->_flags |= 0x100; obj->_flags |= 0x100; } else { bool someFlag = false; PicAniInfo aniInfo; obj->getPicAniInfo(aniInfo); if (obj->_objtype == kObjTypeStaticANIObject && inter->_staticsId1) { StaticANIObject *ani = static_cast<StaticANIObject *>(obj); ani->_messageQueueId = 0; ani->changeStatics2(inter->_staticsId1); } int xpos = inter->_xOffs + obj->_ox; int ypos = inter->_yOffs + obj->_oy; obj->setPicAniInfo(aniInfo); if (abs(xpos - subj->_ox) > 1 || abs(ypos - subj->_oy) > 1 || (inter->_staticsId2 != 0 && (subj->_statics == 0 || subj->_statics->_staticsId != inter->_staticsId2))) { mq = getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->startMove(subj, xpos, ypos, 1, inter->_staticsId2); if (!mq) return false; ex = new ExCommand(subj->_id, 55, 0, 0, 0, 0, 1, 0, 0, 0); ex->_x = obj->_id; ex->_y = obj->_odelay; ex->_param = subj->_odelay; ex->_excFlags = 3; ex->_field_20 = invId; ex->_z = (obj->_objtype != kObjTypePictureObject); mq->addExCommandToEnd(ex); someFlag = true; ex = new ExCommand(subj->_id, 17, 0x40, 0, 0, 0, 1, 0, 0, 0); ex->_x = xpos; ex->_y = ypos; ex->_excFlags |= 3; ex->_param = 6; ex->_z = obj->_id; ex->_field_20 = obj->_odelay; ex->postMessage(); } if (!inter->_staticsId1 || !(inter->_flags & 1)) return true; if (obj->_objtype != kObjTypeStaticANIObject) return false; StaticANIObject *ani = static_cast<StaticANIObject *>(obj); if (!ani->isIdle()) return false; if (ani->getMessageQueue()) ani->queueMessageQueue(0); if (!ani->_statics || ani->_statics->_staticsId != inter->_staticsId1 || ani->_movement) { mq = ani->changeStatics1(inter->_staticsId1); if (!mq) return false; if (someFlag) { if (!(inter->_flags & 0x10000)) { if (mq->_isFinished) { ani->_flags |= 0x80u; } else { ex = new ExCommand(ani->_id, 34, 0x80, 0, 0, 0, 1, 0, 0, 0); ex->_z = 0x80; ex->_param = ani->_odelay; ex->_excFlags = 3; mq->addExCommandToEnd(ex); } } ex = new ExCommand(ani->_id, 34, 0x100, 0, 0, 0, 1, 0, 0, 0); ex->_param = ani->_odelay; ex->_z = 0x100; ex->_excFlags = 3; mq->addExCommandToEnd(ex); } else { ex = new ExCommand(subj->_id, 55, 0, 0, 0, 0, 1, 0, 0, 0); ex->_x = ani->_id; ex->_y = ani->_odelay; ex->_param = subj->_odelay; ex->_excFlags = 2; ex->_z = (obj->_objtype != kObjTypePictureObject); ex->_field_20 = invId; mq->addExCommandToEnd(ex); if (!mq->_isFinished) return true; mq->_isFinished = 0; ani->queueMessageQueue(mq); } } else { obj->_flags |= 0x100; if (inter->_flags & 0x10000) return true; obj->_flags |= 0x80; } } return true; }