/*---------------------------------------------------------------------*//** 未定義の関数を外部関数によって解決を試みる @param codeExtScriptOut 追加スクリプトコード(戻り値 false の場合有効) @param paramParse 解析汎用パラメータ @retval true 解析を終了してよし ※ 外部拡張ネイティブ関数追加によって解決した場合も この戻り値でよい @retval false 解析を続ける ※ codeExtScriptOut に該当関数のスクリプトコードを 設定して、解決を試みる **//*---------------------------------------------------------------------*/ bool EsExternalExtension::resolveUndefinedFunctionByExtFunc(VcString* codeExtScriptOut, EsExtParam paramParse) { // 関数呼び出しが解決しているか調べる s32 numUnresolvedFuncCall = 0; for(ListIterator<EsParsedFuncInfo*> itCall = _listParsedFuncInfo->iterator(); itCall.has(); itCall.next()) { if(itCall.object()->getKind() != EsParsedFuncInfo::KIND_CALL) { continue; } const VcString* nameCall = itCall.object()->getFuncName(); bool isDefFind = false; // スクリプト内定義関数から探す for(ListIterator<EsParsedFuncInfo*> itDef = _listParsedFuncInfo->iterator(); itDef.has(); itDef.next()) { if(itDef.object()->getKind() != EsParsedFuncInfo::KIND_DEF) { continue; } if(nameCall->equals(itDef.object()->getFuncName())) { isDefFind = true; break; } } if(!isDefFind) { // 既に追加済みの外部拡張ネイティブ関数から探す for(ListIterator<EsExtNativeFunc*> itEnf = _listExtNativeFunc->iterator(); itEnf.has(); itEnf.next()) { if(nameCall->equals(itEnf.object()->getName())) { isDefFind = true; break; } } } itCall.object()->setUnresolved(!isDefFind); // 未解決フラグを立てる if(!isDefFind) { numUnresolvedFuncCall++; } } if(numUnresolvedFuncCall <= 0) // 未解決の関数呼び出しはない { return true; // 解析を終わって問題ない } // 外部のスクリプト追加、もしくは外部拡張ネイティブ関数追加で解決を試みる bool isEndParse = true; // 特に処理が入らなければ解決を終了する for(ListIterator<EsParsedFuncInfo*> itCall = _listParsedFuncInfo->iterator(); itCall.has(); itCall.next()) { if(itCall.object()->getKind() != EsParsedFuncInfo::KIND_CALL) { continue; } if(!itCall.object()->isUnresolved()) { continue; } if(!resolveUndefinedFunction(codeExtScriptOut, itCall.object()->getFuncName(), paramParse)) { isEndParse = false; } } return isEndParse; }
/*---------------------------------------------------------------------*//** 自動開始イベントの開始 **//*---------------------------------------------------------------------*/ bool StoryManager::beginAutoBeginEvent(s32 kind) { bool isBegin = false; for(ListIterator<AutoBeginEventInfo*> it = _listAutoBeginEvi->iterator(); it.has(); it.next()) { AutoBeginEventInfo* abevi = it.object(); if(abevi->getKind() == kind) // 同じ種別 { // イベント起動原因と起動判定 short cid = EventCause::CID_NULL; bool isCall = true; switch(kind) { case AutoBeginEventInfo::KIND_STORY_START: cid = EventCause::CID_STORYSTART; break; case AutoBeginEventInfo::KIND_LOAD_INTVEV_START: cid = EventCause::CID_INTVLEVSTART; break; case AutoBeginEventInfo::KIND_MAP_START: cid = EventCause::CID_MAPSTART; if(Game::getGame()->getMoveMap()->getCurMapId() != abevi->getMapId()) { isCall = false; } break; } // イベント起動 if(isCall) { u16 evid = abevi->getCallEvi()->getInfo(abevi->getActiveCallEviIndex())->getEvid(); if(evid != 0) // わざわざ起動しない設定で上書きすることもありうる { EvCause evcause(cid); EventMatter* matter = (EventMatter*)_evsysRef->begin(evid, 0, &evcause); if(matter != 0L) { isBegin = true; // イベントが複数定義されている場合は、次に送る if(abevi->getCallEvi()->getInfoNum() >= 2) { abevi->nextCallEvi(false); } } } } } } return isBegin; }
/*---------------------------------------------------------------------*//** シリアライズ **//*---------------------------------------------------------------------*/ bool StoryManager::serialize(Serializer* ser) const { // 実行中の Act イベント ID を得る u16 evidActing = 0; EventData* evdat = Game::getGame()->getEventSys()->getEventData(); ASSERT(evdat != 0L); for(int imat = 0; imat < evdat->getEventMatterNum(); imat++) { EventMatter* matterWk = evdat->getEventMatter(imat); if((matterWk->getMatterType() == EMTYPE_ACT) && matterWk->isBegin()) // 開始済み ActMatter 判定 { evidActing = matterWk->getEvId(); } } // ストーリーの保存 if(ser->isStructureMode()) // ストラクチャモード { SaveStructure* svst = (SaveStructure*)ser->getStructure(); svst->_gamesvst._storyid = _storyid; // ストーリー ID の書き込み svst->_gamesvst._isPlayedStoryStartupEvent = _isPlayedStoryStartupEvent; // ストーリー開始イベント起動フラグの書き込み svst->_gamesvst._evidActing = evidActing; // 実行中の Act イベント ID の書き込み } else // ダイレクトモード { ser->store(&_storyid); // ストーリー ID の書き込み ser->store(&_isPlayedStoryStartupEvent); // ストーリー開始イベント起動フラグの書き込み ser->store(&evidActing); // 実行中の Act イベント ID の書き込み } // 配置オブジェクトの状態を保存する if(ser->isStructureMode()) // ストラクチャモード { SaveStructure* svst = (SaveStructure*)ser->getStructure(); if(!svst->storePlacementObjData(_listPlaceObj)) { return false; } } else // ダイレクトモード { s32 numPobj = _listPlaceObj->getCount(); ser->store(&numPobj); for(ListIterator<PlacementObj*> it = _listPlaceObj->iterator(); it.has(); it.next()) { const PlacementObj* pobj = it.object(); pobj->serialize(ser); } } // ワールドマップのシリアライズ _wmap->serialize(ser); return true; }
/*---------------------------------------------------------------------*//** ストーリーの解放 **//*---------------------------------------------------------------------*/ void StoryManager::releaseStory() { // ストーリーを削除 if(_stmod != 0L) { _stmod->destroy(); delete _stmod; _stmod = 0L; } // マップ置換イベントを戻す EventData* evdat = _evsysRef->getEventData(); for(ListIterator<OverrideEventMatter*> it = _listOvrdEvm->iterator(); it.has(); it.next()) { const OverrideEventMatter* oem = it.object(); if(oem->getKind() == OverrideEventMatter::KIND_MAP) // タイプがマップのもののみ { evdat->unoverrideMatter(oem); } } _listOvrdEvm->removeAll(); // 置換イベント情報クリア // 配置オブジェクト情報クリア for(ListIterator<PlacementObj*> it = _listPlaceObj->iterator(); it.has(); it.next()) { PlacementObj* pobj = it.object(); if(pobj->getMapId() == Game::getGame()->getMoveMap()->getCurMapId()) { Game::getGame()->getMap()->unplacePlacementObj(pobj); // 配置解除 } } _listPlaceObj->removeAll(); // 自動起動イベントリストをクリア _listAutoBeginEvi->removeAll(); // その他の値をクリア _storyid = 0L; _isPlayedStoryStartupEvent = false; }
SRCR_BEGIN_NS //////////////////////////////////////////////////////////////////////////// // クラス //========================================================================== // SaveStructure メソッド // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // 外部サービス /*---------------------------------------------------------------------*//** 配置オブジェクトリストのセーブデータを保存する @param listPlaceObj 配置オブジェクトリスト @retval true 成功 @retval false 失敗 **//*---------------------------------------------------------------------*/ bool SaveStructure::storePlacementObjData(const List<PlacementObj*>* listPlaceObj) { // 末端を得る s32 idx = 0; while(idx < NUM_POBJ_MAX) { if(_pobjsvst[idx]._ucase == 0) // 未記録 { break; } idx++; } for(ListIterator<PlacementObj*> it = listPlaceObj->iterator(); it.has(); it.next()) { if(idx >= NUM_POBJ_MAX) { ASSERT(idx < NUM_POBJ_MAX); return false; } const PlacementObj* pobj = it.object(); if(!pobj->isNullState()) // 初期状態以外なら { PlacementObj::SaveStructure* pobjsvst = &_pobjsvst[idx]; pobj->storeToStructure(pobjsvst); // 保存 idx++; } } ASSERT(idx <= NUM_POBJ_MAX); return true; }
/*---------------------------------------------------------------------*//** 配置オブジェクトリストへセーブデータを復元する @param listPlaceObj 配置オブジェクトリスト @retval true 成功 @retval false 失敗 **//*---------------------------------------------------------------------*/ bool SaveStructure::restorePlacementObjData(List<PlacementObj*>* listPlaceObj) const { for(ListIterator<PlacementObj*> it = listPlaceObj->iterator(); it.has(); it.next()) { PlacementObj* pobj = it.object(); for(int idx = 0; idx < NUM_POBJ_MAX; idx++) { const PlacementObj::SaveStructure* pobjsvst = &_pobjsvst[idx]; if(isSamePlacementObj(pobjsvst, pobj)) { pobj->restoreFromStructure(pobjsvst); // 復元 break; } } } return true; }
/*---------------------------------------------------------------------*//** 解析関数情報追加 **//*---------------------------------------------------------------------*/ void EsExternalExtension::addParsedFuncInfo(const VcString* nameFunc, bool isDef) { if(_listParsedFuncInfo == 0L) { return; } // 入力された関数の種類 EsParsedFuncInfo::Kind kind = isDef ? EsParsedFuncInfo::KIND_DEF : EsParsedFuncInfo::KIND_CALL; // 重複チェック for(ListIterator<EsParsedFuncInfo*> it = _listParsedFuncInfo->iterator(); it.has(); it.next()) { EsParsedFuncInfo* pfi = it.object(); if( (pfi->getKind() == kind) && (pfi->getFuncName()->equals(nameFunc)) ) { return; // 重複 } } // リストに追加する EsParsedFuncInfo* pfi = new EsParsedFuncInfo(nameFunc, kind); _listParsedFuncInfo->addTail(pfi); }
/*---------------------------------------------------------------------*//** スキルフレーム処理 - 実行中 **//*---------------------------------------------------------------------*/ bool Char1504_Shika_EnemySpirit::execSkillAct(ExecRes* res, const ExecCtx* ec, s32 cntStep, f32 frmcntStep) { const f32 FRAME_STEP = 0.76667f * FRAMERATE; if(cntStep == 1) { setBefaviorMaxFrame(FRAME_STEP); // 最大の行動フレーム数設定 } setBefaviorCurrentFrame(frmcntStep); // 現在の行動フレーム数設定 if(frmcntStep >= FRAME_STEP) // 攻撃フレーム { const CharLogicData* cldat = getCharLogicData(); ASSERT(cldat != 0L); // 範囲内の対象をリストアップ f32 lenEffctvSq = cldat->getSkillRange() * cldat->getSkillRange(); List<Unit*> listUnits; CalcUtils::collectUnitFanRange( &listUnits, getThisUnit()->getPosition(), getThisUnit()->getDirection()->y(), Unit::UNITFLAG_PC, lenEffctvSq, TFW_COS45 ); // ±45°以内 // リストアップしたユニットにクラスタを投げる Unit* unitTrg = 0L; for(ListIterator<Unit*> it = listUnits.iterator(); it.has(); it.next()) { unitTrg = it.object(); break; } #if 1 TransStat tstat; EleneStat eestatSkill(cldat->getSkillOqlElene(), cldat->getSkillCurElene()); tstat.setupForSkill(getThisUnit(), &eestatSkill); MagicInfluencer::serveGeneralMc(getThisUnit(), unitTrg, &tstat, GameParticleDef::PTCLK_SKILL_SHOCK_WAVE); #else MagicSys* mgcsys = Game::getGame()->getMagicSys(); ASSERT(mgcsys != 0L); MagicClusterCreateParam mccprm(MagicClusterType::SERVED, GameParticleDef::PTCLK_SKILL_SHOCK_WAVE); EleneStat eestatSkill(cldat->getSkillOqlElene(), cldat->getSkillCurElene()); Vector3F pos(*getThisUnit()->getCenterPos()); mccprm._unitOwnrRef = getThisUnit(); mccprm._unitMainTrgRef = unitTrg; mccprm._pos = &pos; mccprm._tstat.setupForSkill(getThisUnit(), &eestatSkill); mccprm._lifeframe = cldat->getSkillCurElene()->getWater() / Elene::ELENE_VALID_FIGURE; mccprm._isNoOnlyTrgColl = true; u16 mcidNew = mgcsys->appearCluster(&mccprm); if(mcidNew == 0) { return true; } // 成功ではないが終えるために次のステップへ MagicCluster* mcNew = mgcsys->getCluster(mcidNew); if(mcNew == 0L) { return true; } // 成功ではないが終えるために次のステップへ TFW_SET_FLAG(*mcNew->ctrlFlags(), MagicCluster::CTRLF_DIR_TO_ROTZ, true); // 方向を Z 軸回転に反映させる // クラスタ発射 /* f32 acc = cldat->getSkillCurElene()->getWind() * (0.1f / (f32)Elene::ELENE_VALID_FIGURE); if(acc < 0.033f) { acc = 0.033f; } Vector3F accMc(0.0, 0.0, acc); Matrix4F mtxRot; mtxRot.rotateY(getThisUnit()->getDirection()->y()); mtxRot.mult(&accMc, &accMc); mcNew->accelerate(&accMc); */ f32 speed = cldat->getSkillCurElene()->getWind() * (0.1f / (f32)Elene::ELENE_VALID_FIGURE); if(speed < 0.033f) { speed = 0.033f; } Vector3F velMc(0.0f, 0.0f, speed); Matrix4F mtxRot; mtxRot.rotateY(getThisUnit()->getDirection()->y()); mtxRot.mult(&velMc, &velMc); mcNew->setInitialVelocity(&velMc); mcNew->reflectPosture(); #endif resetBefaviorFrame(); // 行動フレームリセット return true; } return false; // 継続する }
/*---------------------------------------------------------------------*//** デシリアライズ **//*---------------------------------------------------------------------*/ bool StoryManager::deserialize(Serializer* ser) { // ストーリーデータの読み込み s32 storyid = 0; u16 evidActing = 0; bool isPlayedStoryStartupEvent = false; bool isEvIntvl = TFW_IS_FLAG(Game::getGame()->getSaveSys()->getSaveData()->getLoadTimeSaveFlags(), SaveData::SVF_EVENT_INTVL); if(ser->isStructureMode()) // ストラクチャモード { const SaveStructure* svst = (SaveStructure*)ser->getStructure(); storyid = svst->_gamesvst._storyid; // ストーリー ID 値の読み込み isPlayedStoryStartupEvent = svst->_gamesvst._isPlayedStoryStartupEvent; // ストーリー開始イベント起動フラグの読み込み evidActing = svst->_gamesvst._evidActing; // 実行中の Act イベント ID の読み込み } else // ダイレクトモード { ser->restore(&storyid); // ストーリー ID 値の読み込み ser->restore(&isPlayedStoryStartupEvent); // ストーリー開始イベント起動フラグの読み込み ser->restore(&evidActing); // 実行中の Act イベント ID の読み込み } // Volume 1 Lite 版はストーリーが 10203 まで(この実装はあまり美しくない….オーバーライドによる実装を要検討【2010/10/29 r-kishi】) #if defined(_ENLIGHT_V01_LITE) if(storyid > 10203) { storyid = 10203; isPlayedStoryStartupEvent = false; Game::getGame()->getSaveSys()->getSaveData()->setSaveF(SaveIdDef::SFID_ST10203_CORPO_SAY_TOGETHER, false); // [St10203] アサダウン後コルポ合流時のイベントを見ていない } #endif // ストーリーのロード loadStory(storyid); // ストーリーを読み込む _isPlayedStoryStartupEvent = isPlayedStoryStartupEvent; // 配置オブジェクトの状態を読み込む if(ser->isStructureMode()) // ストラクチャモード { SaveStructure* svst = (SaveStructure*)ser->getStructure(); if(!svst->restorePlacementObjData(_listPlaceObj)) { return false; } } else // ダイレクトモード { s32 numPobj = 0; ser->restore(&numPobj); ASSERT(_listPlaceObj->getCount() == numPobj); ListIterator<PlacementObj*> it = _listPlaceObj->iterator(); for(int i = 0; i < numPobj; i++) { if(!it.has()) { ASSERT(false); return false; } PlacementObj* pobj = it.object(); pobj->deserialize(ser); it.next(); } } // ワールドマップのデシリアライズ _wmap->deserialize(ser); // イベント途中セーブデータは再開時イベントをセットする if(isEvIntvl && (evidActing != 0)) { reserveEventForResume(evidActing, true); } return true; }
/*---------------------------------------------------------------------*//** マップ変更後通知 **//*---------------------------------------------------------------------*/ void StoryManager::notifyChangedMap(bool isDeserializeCase) { Map* map = Game::getGame()->getMap(); ASSERT(map != 0L); MoveMap* mvmap = Game::getGame()->getMoveMap(); ASSERT(mvmap != 0L); // マップに脇役を配置 for(ListIterator<PlacementObj*> it = _listPlaceObj->iterator(); it.has(); it.next()) { PlacementObj* pobj = it.object(); if(isDeserializeCase) // セーブデータ読み込み時 { if(pobj->isPlaced()) // 配置済み { map->placePlacementObj(pobj, true); // マップ配置を復元 } else if(pobj->isNewPlacedCondition()) { map->placePlacementObj(pobj, false); // マップに通常条件配置 } } else { if(pobj->isNewPlacedCondition()) { map->placePlacementObj(pobj, false); // マップに配置 } else if(pobj->isPlaced()) // 配置済み { map->unplacePlacementObj(pobj); // 配置解除 } } } // マップ置換イベントを処理 EventData* evdat = _evsysRef->getEventData(); for(ListIterator<OverrideEventMatter*> it = _listOvrdEvm->iterator(); it.has(); it.next()) { const OverrideEventMatter* oem = it.object(); if(oem->getKind() == OverrideEventMatter::KIND_MAP) // タイプがマップのもののみ { if(oem->isCondition()) { evdat->overrideMatter(oem); } } } // マップモジュールを作成 _mapmod = MapModFactory::makeMapMod(mvmap->getCurMapId()); ASSERT(_mapmod != 0L); // マップ開始時イベントを起動 beginAutoBeginEvent(AutoBeginEventInfo::KIND_MAP_START); // 各通知処理 ASSERT(_stmod != 0L); _stmod->onDecisionParty(mvmap->getCurMapId(), mvmap->getPrevMapId()); _stmod->notifyChangedMap(mvmap->getCurMapId(), mvmap->getPrevMapId()); _mapmod->begin(); _wmap->notifyChangedMap(); }