40 :m_silent_mode(silent_mode)
56 Ogre::DataStreamPtr datastream = Ogre::ResourceGroupManager::getSingleton().openResource(entry->
fname, entry->
resource_group);
66 Keyword block = Keyword::INVALID;
82 keyword = Keyword::SET_MANAGEDMATERIALS_OPTIONS;
84 if (
keyword != Keyword::INVALID)
86 if (
keyword == Keyword::SET_MANAGEDMATERIALS_OPTIONS)
92 else if (keyword == Keyword::MANAGEDMATERIALS
94 ||
keyword == Keyword::FLEXBODIES
123 catch (Ogre::Exception& e)
127 fmt::format(
"Could not use addonpart: Error parsing file '{}', message: {}",
128 entry->
fname, e.getFullDescription()));
145 Ogre::DataStreamPtr datastream = Ogre::ResourceGroupManager::getSingleton().openResource(addonpart_entry->
fname, addonpart_entry->
resource_group);
184 catch (Ogre::Exception& e)
188 fmt::format(
"Addonpart unwanted elements check: Error parsing file '{}', message: {}",
189 addonpart_entry->
fname, e.getFullDescription()));
224 if (str ==
"mesh_standard") def.
type = ManagedMaterialType::MESH_STANDARD;
225 if (str ==
"mesh_transparent") def.
type = ManagedMaterialType::MESH_TRANSPARENT;
226 if (str ==
"flexmesh_standard") def.
type = ManagedMaterialType::FLEXMESH_STANDARD;
227 if (str ==
"flexmesh_transparent") def.
type = ManagedMaterialType::FLEXMESH_TRANSPARENT;
240 m_module->managedmaterials.push_back(def);
260 fmt::format(
"Error parsing addonpart file '{}': 'install_prop' has only {} arguments, expected {}",
265 int importflags = Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NUMBERED;
283 case SpecialProp::BEACON:
294 case SpecialProp::DASHBOARD_LEFT:
295 case SpecialProp::DASHBOARD_RIGHT:
326 fmt::format(
"Error parsing addonpart file '{}': flexbody has only {} arguments, expected {}",
m_addonpart_entry->
fname, n, 10));
330 int importflags = Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NUMBERED;
351 fmt::format(
"Error parsing addonpart file '{}': flexbody is not followed by 'forset'!",
m_addonpart_entry->
fname));
360 for (
unsigned int i = range.start.Num(); i <= range.end.Num(); ++i)
362 Node::Ref ref(
"", i, Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NUMBERED, 0);
367 m_module->flexbodies.push_back(def);
377 fmt::format(
"Error parsing addonpart file '{}': flare has only {} arguments, expected {}",
m_addonpart_entry->
fname, n, 5));
382 int importflags = Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NUMBERED;
415 fmt::format(
"Error parsing addonpart file '{}': flare2 has only {} arguments, expected {}",
m_addonpart_entry->
fname, n, 6));
420 int importflags = Node::Ref::REGULAR_STATE_IS_VALID | Node::Ref::REGULAR_STATE_IS_NUMBERED;
458 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': marking prop '{}' as UNWANTED",
463 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': skipping prop '{}' because it's marked PROTECTED",
482 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': marking flexbody '{}' as UNWANTED",
487 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': skipping flexbody '{}' because it's marked PROTECTED",
506 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': marking flare '{}' as UNWANTED",
511 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': skipping flare '{}' because it's marked PROTECTED",
530 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': marking exhaust '{}' as UNWANTED",
535 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': skipping exhaust '{}' because it's marked PROTECTED",
555 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': marking managedmaterial '{}' as UNWANTED",
560 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': skipping managedmaterial '{}' because it's marked PROTECTED",
592 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': Sheduling tweak for wheel '{}'"
593 " with params {{ media1={}, media2={}, side={}, tire_radius={}, rim_radius={} }}",
599 this->
Log(fmt::format(
"[RoR|Addonpart] WARNING: file '{}', directive '{}': Resetting tweaks for wheel '{}' due to conflict with '{}'",
608 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': skipping wheel '{}' because it's marked PROTECTED",
637 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': Scheduling tweak for node '{}'"
638 " with params {{ x={}, y={}, z={} }}",
644 this->
Log(fmt::format(
"[RoR|Addonpart] WARNING: file '{}', directive '{}': Resetting tweaks for node '{}' due to conflict with '{}'",
653 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': skipping node '{}' because it's marked PROTECTED",
682 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': Scheduling tweak for cinecam '{}'"
683 " with params {{ x={}, y={}, z={} }}",
689 this->
Log(fmt::format(
"[RoR|Addonpart] WARNING: file '{}', directive '{}': Resetting tweaks for cinecam '{}' due to conflict with '{}'",
698 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': skipping cinecam '{}' because it's marked PROTECTED",
735 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': Scheduling tweak for flexbody '{}'"
736 " with params {{ offsetX={}, offsetY={}, offsetZ={}, rotX={}, rotY={}, rotZ={}, media={} }}",
743 this->
Log(fmt::format(
"[RoR|Addonpart] WARNING: file '{}', directive '{}': Resetting tweaks for flexbody '{}' due to conflict with '{}'",
752 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': skipping flexbody '{}' because it's marked PROTECTED",
791 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': Scheduling tweak for prop '{}'"
792 " with params {{ media1={}, offsetX={}, offsetY={}, offsetZ={}, rotX={}, rotY={}, rotZ={}, media2={} }}",
800 this->
Log(fmt::format(
"[RoR|Addonpart] WARNING: file '{}', directive '{}': Resetting tweaks for prop '{}' due to conflict with '{}'",
809 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': skipping prop '{}' because it's marked PROTECTED",
840 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': Scheduling tweak for managed material '{}'"
841 " with params {{ type={}, media1={}, media2={}, media3={} }}",
846 this->
Log(fmt::format(
"[RoR|Addonpart] WARNING: file '{}', directive '{}': Resetting tweaks for managed material '{}' due to conflict with '{}'",
855 this->
Log(fmt::format(
"[RoR|Addonpart] INFO: file '{}', directive '{}': skipping managed material '{}' because it's marked PROTECTED",
863 LOG(fmt::format(
"[RoR|Addonpart] -- Performing `RecordAddonpartConflicts()` between '{}' and '{}' ~ this involves generating dummy tuneups (hence messages below) --", addonpart1->
fname, addonpart2->
fname));
885 NodeNum_t suspect = i_pair.second.tnt_nodenum;
889 conflicts.push_back(
AddonPartConflict{addonpart1, addonpart2,
"addonpart_tweak_node", (int)suspect});
890 LOG(fmt::format(
"[RoR|Addonpart] Found conflict between '{}' and '{}' - node {} is tweaked by both", addonpart1->
fname, addonpart2->
fname, (
int)suspect));
897 WheelID_t suspect = i_pair.second.twt_wheel_id;
901 conflicts.push_back(
AddonPartConflict{addonpart1, addonpart2,
"addonpart_tweak_wheel", (int)suspect});
902 LOG(fmt::format(
"[RoR|Addonpart] Found conflict between '{}' and '{}' - wheel {} is tweaked by both", addonpart1->
fname, addonpart2->
fname, (
int)suspect));
909 PropID_t suspect = i_pair.second.tpt_prop_id;
913 conflicts.push_back(
AddonPartConflict{addonpart1, addonpart2,
"addonpart_tweak_prop", (int)suspect});
914 LOG(fmt::format(
"[RoR|Addonpart] Found conflict between '{}' and '{}' - prop {} is tweaked by both", addonpart1->
fname, addonpart2->
fname, (
int)suspect));
925 conflicts.push_back(
AddonPartConflict{addonpart1, addonpart2,
"addonpart_tweak_flexbody", (int)suspect});
926 LOG(fmt::format(
"[RoR|Addonpart] Found conflict between '{}' and '{}' - flexbody {} is tweaked by both", addonpart1->
fname, addonpart2->
fname, (
int)suspect));
930 LOG(fmt::format(
"[RoR|Addonpart] -- Done with `RecordAddonpartConflicts()` between '{}' and '{}' --", addonpart1->
fname, addonpart2->
fname));
935 if (!addonpart1 || !addonpart2)
942 if ((conflict.atc_addonpart1 == addonpart1 && conflict.atc_addonpart2 == addonpart2) ||
943 (conflict.atc_addonpart1 == addonpart2 && conflict.atc_addonpart2 == addonpart1))
971 if (conflicts.size() > 0)
976 dialog->
mbc_title =
_LC(
"Tuning",
"Cannot install addon part, conflicts were detected.");
977 dialog->
mbc_text = fmt::format(
_LC(
"Tuning",
"Requested addon part: '{}' (file '{}')."), addonpart_entry->
dname, addonpart_entry->
fname);
979 dialog->
mbc_text += fmt::format(
_LC(
"Tuning",
"Total conflicts: {}."), conflicts.size());
981 for (
size_t i=0; i < conflicts.size(); i++)
984 dialog->
mbc_text += fmt::format(
_LC(
"Tuning",
"[{}/{}] '{}' (file '{}') conflicts with '{}' #{}."),
985 i+1, conflicts.size(),
986 conflicts[i].atc_addonpart2->dname, conflicts[i].atc_addonpart2->fname,
987 conflicts[i].atc_keyword, conflicts[i].atc_element_id);
999 return conflicts.size() > 0;
Central state/object manager and communications hub.
#define ROR_ASSERT(_EXPR)
void LOG(const char *msg)
Legacy alias - formerly a macro.
A database of user-installed content alias 'mods' (vehicles, terrains...)
Game state manager and message-queue provider.
Checks the rig-def file syntax and loads data to memory.
Legacy parser resolved references on-the-fly and the condition to check named nodes was "are there an...
static void ProcessForsetLine(RigDef::Flexbody &def, const std::string &line, int line_number=-1)
static SpecialProp IdentifySpecialProp(const std::string &str)
static Keyword IdentifyKeyword(const std::string &line)
TuneupDefPtr & getWorkingTuneupDef()
NOTE: Modcache processes this format directly using RoR::GenericDocument, see RoR::CacheSystem::FillA...
static bool CheckForAddonpartConflict(CacheEntryPtr addonpart1, CacheEntryPtr addonpart2, AddonPartConflictVec &conflicts)
void ProcessUnwantedProp()
AddonPartUtility(bool silent_mode=false)
static void RecordAddonpartConflicts(CacheEntryPtr addonpart1, CacheEntryPtr addonpart2, AddonPartConflictVec &conflicts)
void ProcessUnwantedManagedMat()
bool m_silent_mode
To block logging during conflict resolution (which works by generating dummy tuneups - would confuse ...
GenericDocContextPtr m_context
std::shared_ptr< RigDef::Document::Module > TransformToRigDefModule(CacheEntryPtr &addonpart_entry)
transforms the addonpart to RigDef::File::Module (fake 'section/end_section') used for spawning.
void ProcessUnwantedFlare()
GenericDocumentPtr m_document
void ProcessUnwantedFlexbody()
void Log(const std::string &text)
std::shared_ptr< RigDef::Document::Module > m_module
void ProcessDirectiveSetManagedMaterialsOptions()
RigDef::ManagedMaterialsOptions m_managedmaterials_options
void ResolveUnwantedAndTweakedElements(TuneupDefPtr &tuneup, CacheEntryPtr &addonpart_entry)
Evaluates 'addonpart_unwanted_*' elements, respecting 'protected_*' directives in the tuneup.
static void ResetUnwantedAndTweakedElements(TuneupDefPtr &tuneup)
void ProcessManagedMaterial()
void ProcessTweakFlexbody()
CacheEntryPtr m_addonpart_entry
void ProcessUnwantedExhaust()
void ProcessTweakCineCamera()
static bool DoubleCheckForAddonpartConflict(ActorPtr target_actor, CacheEntryPtr addonpart_entry)
void ProcessTweakManagedMat()
Ogre::String fname
filename
TuneupDefPtr addonpart_data_only
Cached addonpart data (dummy tuneup), only used for evaluating conflicts, see AddonPartUtility::Recor...
Ogre::String dname
name parsed from the file
Ogre::String resource_group
Resource group of the loaded bundle. Empty if not loaded yet.
CacheEntryPtr FindEntryByFilename(RoR::LoaderType type, bool partial, const std::string &_filename_maybe_bundlequalified)
Returns NULL if none found; "Bundle-qualified" format also specifies the ZIP/directory in modcache,...
void LoadResource(CacheEntryPtr &t)
Loads the associated resource bundle if not already done.
@ CONSOLE_MSGTYPE_ACTOR
Parsing/spawn/simulation messages for actors.
void putMessage(MessageArea area, MessageType type, std::string const &msg, std::string icon="")
void PushMessage(Message m)
Doesn't guarantee order! Use ChainMessage() if order matters.
static bool isWheelTweaked(TuneupDefPtr &tuneup_entry, WheelID_t wheel_id, TuneupWheelTweak *&out_tweak)
static bool isNodeTweaked(TuneupDefPtr &tuneup_entry, NodeNum_t nodenum, TuneupNodeTweak *&out_tweak)
static bool isFlexbodyTweaked(TuneupDefPtr &tuneup_entry, FlexbodyID_t flexbody_id, TuneupFlexbodyTweak *&out_tweak)
static bool isPropTweaked(TuneupDefPtr &tuneup_entry, PropID_t flexbody_id, TuneupPropTweak *&out_tweak)
@ MSG_GUI_HIDE_MESSAGE_BOX_REQUESTED
@ MSG_GUI_SHOW_MESSAGE_BOX_REQUESTED
Payload = MessageBoxConfig* (owner)
GameContext * GetGameContext()
CacheSystem * GetCacheSystem()
int CineCameraID_t
Index into Actor::ar_cinecam_node and Actor::ar_camera_node_* arrays; use RoR::CINECAMERAID_INVALID a...
int WheelID_t
Index to Actor::ar_wheels, use RoR::WHEELID_INVALID as empty value.
int PropID_t
Index to GfxActor::m_props, use RoR::PROPID_INVALID as empty value.
int FlareID_t
Index into Actor::ar_flares, use RoR::FLAREID_INVALID as empty value.
int ExhaustID_t
Index into GfxActor::m_exhausts, use RoR::EXHAUSTID_INVALID as empty value.
int FlexbodyID_t
Index to GfxActor::m_flexbodies, use RoR::FLEXBODYID_INVALID as empty value.
uint16_t NodeNum_t
Node position within Actor::ar_nodes; use RoR::NODENUM_INVALID as empty value.
std::vector< AddonPartConflict > AddonPartConflictVec
Ogre::String material_name
int control_number
Only 'u' type flares.
std::string dashboard_link
Only 'd' type flares.
std::vector< Node::Range > node_list_to_import
std::vector< Node::Ref > node_list
ManagedMaterialsOptions options
Ogre::String specular_map
Ogre::String damaged_diffuse_map
Ogre::String flare_material_name
DashboardSpecial special_prop_dashboard
BeaconSpecial special_prop_beacon
< Conflict between two addonparts tweaking the same element
float mbc_content_width
Parameter to ImGui::SetContentWidth() - hard limit on content size.
std::vector< MessageBoxButton > mbc_buttons
float getTokNumeric(int offset=0) const
bool isTokKeyword(int offset=0) const
std::string getTokKeyword(int offset=0) const
float getTokFloat(int offset=0) const
bool isTokNumeric(int offset=0) const
bool endOfFile(int offset=0) const
bool isTokLineBreak(int offset=0) const
std::string getTokString(int offset=0) const
bool isTokComment(int offset=0) const
bool isTokString(int offset=0) const
bool isTokInt(int offset=0) const
int getTokInt(int offset=0) const
float getFloatData(int offset=0) const
bool isTokFloat(int offset=0) const
const char * getStringData(int offset=0) const
static const BitMask_t OPTION_ALLOW_SLASH_COMMENTS
Allow comments starting with //.
virtual void loadFromDataStream(Ogre::DataStreamPtr datastream, BitMask_t options=0)
static const BitMask_t OPTION_ALLOW_NAKED_STRINGS
Allow strings without quotes, for backwards compatibility.
Unified game event system - all requests and state changes are reported using a message.
< Data of 'addonpart_tweak_cinecam <cinecam ID> <posX> <posY> <posZ>'
CineCameraID_t tct_cinecam_id
Arg#1, required.
Ogre::Vector3 tct_pos
Args#234, required.
std::string tct_origin
Addonpart filename.
std::map< WheelID_t, TuneupWheelTweak > wheel_tweaks
Mesh name and radius overrides via 'addonpart_tweak_wheel'.
bool isFlexbodyProtected(FlexbodyID_t flexbodyid) const
bool isPropProtected(PropID_t propid) const
std::set< PropID_t > unwanted_props
'addonpart_unwanted_prop' directives.
std::set< ExhaustID_t > unwanted_exhausts
'addonpart_unwanted_exhaust' directives.
std::set< FlexbodyID_t > unwanted_flexbodies
'addonpart_unwanted_flexbody' directives.
std::map< PropID_t, TuneupPropTweak > prop_tweaks
Mesh name(s), offset and rotation overrides via 'addonpart_tweak_prop'.
bool isCineCameraProtected(CineCameraID_t cinecamid) const
std::set< FlareID_t > unwanted_flares
'addonpart_unwanted_flare' directives.
std::map< NodeNum_t, TuneupNodeTweak > node_tweaks
Node position overrides via 'addonpart_tweak_node'.
std::set< std::string > use_addonparts
Addonpart filenames.
std::map< FlexbodyID_t, TuneupFlexbodyTweak > flexbody_tweaks
Mesh name, offset and rotation overrides via 'addonpart_tweak_flexbody'.
std::set< std::string > unwanted_managedmats
'addonpart_unwanted_managedmaterial' directives.
bool isWheelProtected(WheelID_t wheelid) const
bool isManagedMatProtected(const std::string &matname) const
bool isExhaustProtected(ExhaustID_t exhaustid) const
std::map< CineCameraID_t, TuneupCineCameraTweak > cinecam_tweaks
Cinecam position overrides via 'addonpart_tweak_cinecam'.
std::map< std::string, TuneupManagedMatTweak > managedmat_tweaks
Managed material overrides via 'addonpart_tweak_managedmaterial'.
bool isNodeProtected(NodeNum_t nodenum) const
bool isFlareProtected(FlareID_t flareid) const
< Data of 'addonpart_tweak_flexbody <flexbody ID> <offsetX> <offsetY> <offsetZ> <rotX> <rotY> <rotZ> ...
FlexbodyID_t tft_flexbody_id
Ogre::Vector3 tft_rotation
std::string tft_origin
Addonpart filename.
< Data of 'addonpart_tweak_managedmaterial <name> <type> <media1> <media2> [<media3>]'
std::string tmt_name
Arg#1, required.
std::string tmt_type
Arg#2, required.
std::string tmt_origin
Addonpart filename.
std::array< std::string, 3 > tmt_media
Arg#3, required, Arg#4, optional, Arg#5, optional.
< Data of 'addonpart_tweak_node <nodenum> <posX> <posY> <posZ>'
std::string tnt_origin
Addonpart filename.
NodeNum_t tnt_nodenum
Arg#1, required.
Ogre::Vector3 tnt_pos
Args#234, required.
< Data of 'addonpart_tweak_prop <prop ID> <offsetX> <offsetY> <offsetZ> <rotX> <rotY> <rotZ> <media1>...
std::string tpt_origin
Addonpart filename.
Ogre::Vector3 tpt_rotation
std::array< std::string, 2 > tpt_media
Media1 = prop mesh; Media2: Steering wheel mesh or beacon flare material.
< Data of 'addonpart_tweak_wheel <wheel ID> <media1> <media2> <side flag> <tire radius> <rim radius>'
WheelSide twt_side
Arg#4, optional, default LEFT (Only applicable to mesh/flexbody wheels)
float twt_tire_radius
Arg#5, optional.
std::array< std::string, 2 > twt_media
twt_media[0] Arg#2, required ('wheels[2]': face material, 'meshwheels[2]/flexbodywheels': rim mesh) t...
std::string twt_origin
Addonpart filename.
WheelID_t twt_wheel_id
Arg#1, required.
float twt_rim_radius
Arg#6, optional, only applies to some wheel types.