// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdpch.h" #include "attack_list.h" #include "sheet_manager.h" #include "global.h" // #include "client_sheets/attack_list_sheet.h" // #include "nel/3d/u_scene.h" // #include "nel/misc/sheet_id.h" // #include H_AUTO_DECL(RZ_AttackList) using namespace NLMISC; using namespace std::rel_ops; extern NL3D::UScene *Scene; CAttackListManager *CAttackListManager::_Instance = NULL; // get a .animation_fx sheet from its name (NULL if not found) static CAnimationFXSetSheet *getAnimFXSetSheetFromName(const std::string &name) { CEntitySheet *sheet = SheetMngr.get(NLMISC::CSheetId(name)); if (!sheet) return NULL; if (sheet->Type == CEntitySheet::ANIMATION_FX_SET) return static_cast(sheet); return NULL; } // build an attack part static void buildAttackPart(const std::string &sheetName, CAnimationFXSet &fxSet, NL3D::UAnimationSet *as) { if (!sheetName.empty()) { CAnimationFXSetSheet *sheet = getAnimFXSetSheetFromName(sheetName); if (sheet) { fxSet.init(sheet, as); } else { nlwarning("Sheet %s not found", sheetName.c_str()); } } } //*********************************************************************************************** CAttack::CAttack() { Sheet = NULL; } //*********************************************************************************************** void CAttack::init(const CAttackSheet *sheet, NL3D::UAnimationSet *as) { nlassert(!Sheet); // init already done if (!sheet) return; Sheet = sheet; // buildAttackPart(Sheet->AttackBeginFX, AttackBeginFX, as); buildAttackPart(Sheet->AttackLoopFX, AttackLoopFX, as); buildAttackPart(Sheet->AttackEndFX, AttackEndFX, as); buildAttackPart(Sheet->AttackStaticObjectCastFX, AttackStaticObjectCastFX, as); buildAttackPart(Sheet->AttackFailFX, AttackFailFX, as); buildAttackPart(Sheet->ProjectileFX, ProjectileFX, as); buildAttackPart(Sheet->ImpactFX, ImpactFX, as); } //*********************************************************************************************** void CAttackList::init(const CAttackListSheet *attackList, NL3D::UAnimationSet *as) { nlassert(_Attacks.empty()); if (!attackList) return; _Attacks.resize(attackList->Attacks.size()); for(uint k = 0; k < _Attacks.size(); ++k) { _Attacks[k].ID = &attackList->Attacks[k].ID; _Attacks[k].Attack.init(&(attackList->Attacks[k].Attack), as); } // sort all attacks for fast retrieval std::sort(_Attacks.begin(), _Attacks.end()); } /* struct CAttackEntryComp { bool operator()(const CAttackListEntry &lhs, const CAttackIDSheet &rhs) const { nlassert(lhs.ID); return *lhs.ID < rhs; } }; */ struct CAttackEntryComp2 { bool operator()(const CAttackListEntry &lhs, const CAttackListEntry &rhs) const { nlassert(lhs.ID); nlassert(rhs.ID); return *lhs.ID < *rhs.ID; } }; //*********************************************************************************************** const CAttack *CAttackList::getAttackFromID(const CAttackIDSheet &id) const { H_AUTO_USE(RZ_AttackList); // vl: changed, this line only work with stlport // std::vector::const_iterator it = std::lower_bound(_Attacks.begin(), _Attacks.end(), id, CAttackEntryComp()); CAttackListEntry ale(&id); std::vector::const_iterator it = std::lower_bound(_Attacks.begin(), _Attacks.end(), ale, CAttackEntryComp2()); if (it == _Attacks.end()) return NULL; if (*(it->ID) != id) return NULL; return &(it->Attack); } //*********************************************************************************************** CAttackListManager &CAttackListManager::getInstance() { H_AUTO_USE(RZ_AttackList) if (_Instance) return *_Instance; _Instance = new CAttackListManager(); return *_Instance; } //*********************************************************************************************** void CAttackListManager::releaseInstance() { if( _Instance ) delete _Instance; _Instance = NULL; } //*********************************************************************************************** void CAttackListManager::init() { if (_AnimationSet) return; // init already done if (!Scene) return; // no scene, can't build anything _AnimationSet = Driver->createAnimationSet(); if (!_AnimationSet) return; std::vector result; std::vector filenames; NLMISC::CSheetId::buildIdVector(result, filenames, "attack_list"); for(uint k = 0; k < result.size(); ++k) { const CAttackListSheet *sheet = dynamic_cast(SheetMngr.get(result[k])); if (sheet) { TAttackListMap::iterator it = _AttackMap.find(filenames[k]); if (it != _AttackMap.end()) { nlwarning("attack list duplicated : %s", filenames[k].c_str()); } CAttackList &al = _AttackMap[filenames[k]]; al.init(sheet, _AnimationSet); } } // auras and links buildAurasFXs(); buildLinkFXs(); } //*********************************************************************************************** void CAttackListManager::release() { if (!_AnimationSet) return; _AttackMap.clear(); if (Driver) Driver->deleteAnimationSet(_AnimationSet); _Auras.release(); _Links.release(); delete _Instance; _Instance = NULL; } //*********************************************************************************************** const CAttackList *CAttackListManager::getAttackList(const std::string &name) const { H_AUTO_USE(RZ_AttackList) TAttackListMap::const_iterator it = _AttackMap.find(name); if (it != _AttackMap.end()) return &(it->second); return NULL; } //*********************************************************************************************** CAttackListManager::CAttackListManager() { _AnimationSet = NULL; } //******************************************************************************************* void CAttackListManager::buildAurasFXs() { _Auras.init("auras.id_to_string_array", _AnimationSet, false /* must not delete animset, owned by this object */); } //******************************************************************************************* void CAttackListManager::buildLinkFXs() { _Links.init("links.id_to_string_array", _AnimationSet, false /* must not delete animset, owned by this object */); }