Merge branch 'dev' into schema-integration

# Conflicts:
#	NewHorizons/Builder/Body/FunnelBuilder.cs
#	NewHorizons/External/Configs/PlanetConfig.cs
#	NewHorizons/External/Configs/StarSystemConfig.cs
#	NewHorizons/External/Modules/AsteroidBeltModule.cs
#	NewHorizons/External/Modules/AtmosphereModule.cs
#	NewHorizons/External/Modules/BaseModule.cs
#	NewHorizons/External/Modules/OrbitModule.cs
#	NewHorizons/External/Modules/PropModule.cs
#	NewHorizons/External/Modules/ShipLogModule.cs
#	NewHorizons/External/Modules/SignalModule.cs
#	NewHorizons/External/Modules/VariableSize/FunnelModule.cs
#	NewHorizons/External/Modules/VariableSize/RingModule.cs
#	NewHorizons/External/Modules/VariableSize/SingularityModule.cs
#	NewHorizons/External/Modules/VariableSize/StarModule.cs
#	NewHorizons/Main.cs
This commit is contained in:
Ben C 2022-05-22 13:24:02 -04:00
commit cbd0109ea0
58 changed files with 2273 additions and 604 deletions

684
.editorconfig Normal file
View File

@ -0,0 +1,684 @@
[*]
charset = utf-8
end_of_line = crlf
indent_size = 4
indent_style = space
insert_final_newline = false
max_line_length = 120
tab_width = 4
trim_trailing_whitespace = false
ij_continuation_indent_size = 8
ij_formatter_off_tag = @formatter:off
ij_formatter_on_tag = @formatter:on
ij_formatter_tags_enabled = false
ij_smart_tabs = false
ij_visual_guides = none
ij_wrap_on_typing = false
[*.css]
ij_css_align_closing_brace_with_properties = false
ij_css_blank_lines_around_nested_selector = 1
ij_css_blank_lines_between_blocks = 1
ij_css_block_comment_add_space = false
ij_css_brace_placement = end_of_line
ij_css_enforce_quotes_on_format = false
ij_css_hex_color_long_format = false
ij_css_hex_color_lower_case = false
ij_css_hex_color_short_format = false
ij_css_hex_color_upper_case = false
ij_css_keep_blank_lines_in_code = 2
ij_css_keep_indents_on_empty_lines = false
ij_css_keep_single_line_blocks = false
ij_css_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
ij_css_space_after_colon = true
ij_css_space_before_opening_brace = true
ij_css_use_double_quotes = true
ij_css_value_alignment = do_not_align
[*.less]
indent_size = 2
ij_less_align_closing_brace_with_properties = false
ij_less_blank_lines_around_nested_selector = 1
ij_less_blank_lines_between_blocks = 1
ij_less_block_comment_add_space = false
ij_less_brace_placement = 0
ij_less_enforce_quotes_on_format = false
ij_less_hex_color_long_format = false
ij_less_hex_color_lower_case = false
ij_less_hex_color_short_format = false
ij_less_hex_color_upper_case = false
ij_less_keep_blank_lines_in_code = 2
ij_less_keep_indents_on_empty_lines = false
ij_less_keep_single_line_blocks = false
ij_less_line_comment_add_space = false
ij_less_line_comment_at_first_column = false
ij_less_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
ij_less_space_after_colon = true
ij_less_space_before_opening_brace = true
ij_less_use_double_quotes = true
ij_less_value_alignment = 0
[*.properties]
ij_properties_align_group_field_declarations = false
ij_properties_keep_blank_lines = false
ij_properties_key_value_delimiter = equals
ij_properties_spaces_around_key_value_delimiter = false
[*.sass]
indent_size = 2
ij_sass_align_closing_brace_with_properties = false
ij_sass_blank_lines_around_nested_selector = 1
ij_sass_blank_lines_between_blocks = 1
ij_sass_brace_placement = 0
ij_sass_enforce_quotes_on_format = false
ij_sass_hex_color_long_format = false
ij_sass_hex_color_lower_case = false
ij_sass_hex_color_short_format = false
ij_sass_hex_color_upper_case = false
ij_sass_keep_blank_lines_in_code = 2
ij_sass_keep_indents_on_empty_lines = false
ij_sass_keep_single_line_blocks = false
ij_sass_line_comment_add_space = false
ij_sass_line_comment_at_first_column = false
ij_sass_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
ij_sass_space_after_colon = true
ij_sass_space_before_opening_brace = true
ij_sass_use_double_quotes = true
ij_sass_value_alignment = 0
[*.scss]
indent_size = 2
ij_scss_align_closing_brace_with_properties = false
ij_scss_blank_lines_around_nested_selector = 1
ij_scss_blank_lines_between_blocks = 1
ij_scss_block_comment_add_space = false
ij_scss_brace_placement = 0
ij_scss_enforce_quotes_on_format = false
ij_scss_hex_color_long_format = false
ij_scss_hex_color_lower_case = false
ij_scss_hex_color_short_format = false
ij_scss_hex_color_upper_case = false
ij_scss_keep_blank_lines_in_code = 2
ij_scss_keep_indents_on_empty_lines = false
ij_scss_keep_single_line_blocks = false
ij_scss_line_comment_add_space = false
ij_scss_line_comment_at_first_column = false
ij_scss_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
ij_scss_space_after_colon = true
ij_scss_space_before_opening_brace = true
ij_scss_use_double_quotes = true
ij_scss_value_alignment = 0
[*.styl]
indent_size = 2
ij_stylus_align_closing_brace_with_properties = false
ij_stylus_blank_lines_around_nested_selector = 1
ij_stylus_blank_lines_between_blocks = 1
ij_stylus_brace_placement = 0
ij_stylus_enforce_quotes_on_format = false
ij_stylus_hex_color_long_format = false
ij_stylus_hex_color_lower_case = false
ij_stylus_hex_color_short_format = false
ij_stylus_hex_color_upper_case = false
ij_stylus_keep_blank_lines_in_code = 2
ij_stylus_keep_indents_on_empty_lines = false
ij_stylus_keep_single_line_blocks = false
ij_stylus_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
ij_stylus_space_after_colon = true
ij_stylus_space_before_opening_brace = true
ij_stylus_use_double_quotes = true
ij_stylus_value_alignment = 0
[*.vue]
indent_size = 2
tab_width = 2
ij_continuation_indent_size = 4
ij_vue_indent_children_of_top_level = template
ij_vue_interpolation_new_line_after_start_delimiter = true
ij_vue_interpolation_new_line_before_end_delimiter = true
ij_vue_interpolation_wrap = off
ij_vue_keep_indents_on_empty_lines = false
ij_vue_spaces_within_interpolation_expressions = true
[.editorconfig]
ij_editorconfig_align_group_field_declarations = false
ij_editorconfig_space_after_colon = false
ij_editorconfig_space_after_comma = true
ij_editorconfig_space_before_colon = false
ij_editorconfig_space_before_comma = false
ij_editorconfig_spaces_around_assignment_operators = true
[{*.ant,*.appxmanifest,*.axml,*.cscfg,*.csdef,*.disco,*.filelayout,*.fxml,*.jhm,*.jnlp,*.jrxml,*.manifest,*.myapp,*.nuspec,*.rng,*.stylecop,*.svcmap,*.tld,*.tps,*.wadcfgx,*.webref,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul,StyleCop.Cache}]
ij_xml_align_attributes = true
ij_xml_align_text = false
ij_xml_attribute_wrap = normal
ij_xml_block_comment_add_space = false
ij_xml_block_comment_at_first_column = true
ij_xml_keep_blank_lines = 2
ij_xml_keep_indents_on_empty_lines = false
ij_xml_keep_line_breaks = true
ij_xml_keep_line_breaks_in_text = true
ij_xml_keep_whitespaces = false
ij_xml_keep_whitespaces_around_cdata = preserve
ij_xml_keep_whitespaces_inside_cdata = false
ij_xml_line_comment_at_first_column = true
ij_xml_space_after_tag_name = false
ij_xml_space_around_equals_in_attribute = false
ij_xml_space_inside_empty_tag = false
ij_xml_text_wrap = normal
[{*.ats,*.cts,*.mts,*.ts}]
ij_continuation_indent_size = 4
ij_typescript_align_imports = false
ij_typescript_align_multiline_array_initializer_expression = false
ij_typescript_align_multiline_binary_operation = false
ij_typescript_align_multiline_chained_methods = false
ij_typescript_align_multiline_extends_list = false
ij_typescript_align_multiline_for = true
ij_typescript_align_multiline_parameters = true
ij_typescript_align_multiline_parameters_in_calls = false
ij_typescript_align_multiline_ternary_operation = false
ij_typescript_align_object_properties = 0
ij_typescript_align_union_types = false
ij_typescript_align_var_statements = 0
ij_typescript_array_initializer_new_line_after_left_brace = false
ij_typescript_array_initializer_right_brace_on_new_line = false
ij_typescript_array_initializer_wrap = off
ij_typescript_assignment_wrap = off
ij_typescript_binary_operation_sign_on_next_line = false
ij_typescript_binary_operation_wrap = off
ij_typescript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
ij_typescript_blank_lines_after_imports = 1
ij_typescript_blank_lines_around_class = 1
ij_typescript_blank_lines_around_field = 0
ij_typescript_blank_lines_around_field_in_interface = 0
ij_typescript_blank_lines_around_function = 1
ij_typescript_blank_lines_around_method = 1
ij_typescript_blank_lines_around_method_in_interface = 1
ij_typescript_block_brace_style = end_of_line
ij_typescript_block_comment_add_space = false
ij_typescript_block_comment_at_first_column = true
ij_typescript_call_parameters_new_line_after_left_paren = false
ij_typescript_call_parameters_right_paren_on_new_line = false
ij_typescript_call_parameters_wrap = off
ij_typescript_catch_on_new_line = false
ij_typescript_chained_call_dot_on_new_line = true
ij_typescript_class_brace_style = end_of_line
ij_typescript_comma_on_new_line = false
ij_typescript_do_while_brace_force = never
ij_typescript_else_on_new_line = false
ij_typescript_enforce_trailing_comma = keep
ij_typescript_enum_constants_wrap = on_every_item
ij_typescript_extends_keyword_wrap = off
ij_typescript_extends_list_wrap = off
ij_typescript_field_prefix = _
ij_typescript_file_name_style = relaxed
ij_typescript_finally_on_new_line = false
ij_typescript_for_brace_force = never
ij_typescript_for_statement_new_line_after_left_paren = false
ij_typescript_for_statement_right_paren_on_new_line = false
ij_typescript_for_statement_wrap = off
ij_typescript_force_quote_style = false
ij_typescript_force_semicolon_style = false
ij_typescript_function_expression_brace_style = end_of_line
ij_typescript_if_brace_force = never
ij_typescript_import_merge_members = global
ij_typescript_import_prefer_absolute_path = global
ij_typescript_import_sort_members = true
ij_typescript_import_sort_module_name = false
ij_typescript_import_use_node_resolution = true
ij_typescript_imports_wrap = on_every_item
ij_typescript_indent_case_from_switch = true
ij_typescript_indent_chained_calls = true
ij_typescript_indent_package_children = 0
ij_typescript_jsdoc_include_types = false
ij_typescript_jsx_attribute_value = braces
ij_typescript_keep_blank_lines_in_code = 2
ij_typescript_keep_first_column_comment = true
ij_typescript_keep_indents_on_empty_lines = false
ij_typescript_keep_line_breaks = true
ij_typescript_keep_simple_blocks_in_one_line = false
ij_typescript_keep_simple_methods_in_one_line = false
ij_typescript_line_comment_add_space = true
ij_typescript_line_comment_at_first_column = false
ij_typescript_method_brace_style = end_of_line
ij_typescript_method_call_chain_wrap = off
ij_typescript_method_parameters_new_line_after_left_paren = false
ij_typescript_method_parameters_right_paren_on_new_line = false
ij_typescript_method_parameters_wrap = off
ij_typescript_object_literal_wrap = on_every_item
ij_typescript_parentheses_expression_new_line_after_left_paren = false
ij_typescript_parentheses_expression_right_paren_on_new_line = false
ij_typescript_place_assignment_sign_on_next_line = false
ij_typescript_prefer_as_type_cast = false
ij_typescript_prefer_explicit_types_function_expression_returns = false
ij_typescript_prefer_explicit_types_function_returns = false
ij_typescript_prefer_explicit_types_vars_fields = false
ij_typescript_prefer_parameters_wrap = false
ij_typescript_reformat_c_style_comments = false
ij_typescript_space_after_colon = true
ij_typescript_space_after_comma = true
ij_typescript_space_after_dots_in_rest_parameter = false
ij_typescript_space_after_generator_mult = true
ij_typescript_space_after_property_colon = true
ij_typescript_space_after_quest = true
ij_typescript_space_after_type_colon = true
ij_typescript_space_after_unary_not = false
ij_typescript_space_before_async_arrow_lparen = true
ij_typescript_space_before_catch_keyword = true
ij_typescript_space_before_catch_left_brace = true
ij_typescript_space_before_catch_parentheses = true
ij_typescript_space_before_class_lbrace = true
ij_typescript_space_before_class_left_brace = true
ij_typescript_space_before_colon = true
ij_typescript_space_before_comma = false
ij_typescript_space_before_do_left_brace = true
ij_typescript_space_before_else_keyword = true
ij_typescript_space_before_else_left_brace = true
ij_typescript_space_before_finally_keyword = true
ij_typescript_space_before_finally_left_brace = true
ij_typescript_space_before_for_left_brace = true
ij_typescript_space_before_for_parentheses = true
ij_typescript_space_before_for_semicolon = false
ij_typescript_space_before_function_left_parenth = true
ij_typescript_space_before_generator_mult = false
ij_typescript_space_before_if_left_brace = true
ij_typescript_space_before_if_parentheses = true
ij_typescript_space_before_method_call_parentheses = false
ij_typescript_space_before_method_left_brace = true
ij_typescript_space_before_method_parentheses = false
ij_typescript_space_before_property_colon = false
ij_typescript_space_before_quest = true
ij_typescript_space_before_switch_left_brace = true
ij_typescript_space_before_switch_parentheses = true
ij_typescript_space_before_try_left_brace = true
ij_typescript_space_before_type_colon = false
ij_typescript_space_before_unary_not = false
ij_typescript_space_before_while_keyword = true
ij_typescript_space_before_while_left_brace = true
ij_typescript_space_before_while_parentheses = true
ij_typescript_spaces_around_additive_operators = true
ij_typescript_spaces_around_arrow_function_operator = true
ij_typescript_spaces_around_assignment_operators = true
ij_typescript_spaces_around_bitwise_operators = true
ij_typescript_spaces_around_equality_operators = true
ij_typescript_spaces_around_logical_operators = true
ij_typescript_spaces_around_multiplicative_operators = true
ij_typescript_spaces_around_relational_operators = true
ij_typescript_spaces_around_shift_operators = true
ij_typescript_spaces_around_unary_operator = false
ij_typescript_spaces_within_array_initializer_brackets = false
ij_typescript_spaces_within_brackets = false
ij_typescript_spaces_within_catch_parentheses = false
ij_typescript_spaces_within_for_parentheses = false
ij_typescript_spaces_within_if_parentheses = false
ij_typescript_spaces_within_imports = false
ij_typescript_spaces_within_interpolation_expressions = false
ij_typescript_spaces_within_method_call_parentheses = false
ij_typescript_spaces_within_method_parentheses = false
ij_typescript_spaces_within_object_literal_braces = false
ij_typescript_spaces_within_object_type_braces = true
ij_typescript_spaces_within_parentheses = false
ij_typescript_spaces_within_switch_parentheses = false
ij_typescript_spaces_within_type_assertion = false
ij_typescript_spaces_within_union_types = true
ij_typescript_spaces_within_while_parentheses = false
ij_typescript_special_else_if_treatment = true
ij_typescript_ternary_operation_signs_on_next_line = false
ij_typescript_ternary_operation_wrap = off
ij_typescript_union_types_wrap = on_every_item
ij_typescript_use_chained_calls_group_indents = false
ij_typescript_use_double_quotes = true
ij_typescript_use_explicit_js_extension = auto
ij_typescript_use_path_mapping = always
ij_typescript_use_public_modifier = false
ij_typescript_use_semicolon_after_statement = true
ij_typescript_var_declaration_wrap = normal
ij_typescript_while_brace_force = never
ij_typescript_while_on_new_line = false
ij_typescript_wrap_comments = false
[{*.bash,*.sh,*.zsh}]
indent_size = 2
tab_width = 2
ij_shell_binary_ops_start_line = false
ij_shell_keep_column_alignment_padding = false
ij_shell_minify_program = false
ij_shell_redirect_followed_by_space = false
ij_shell_switch_cases_indented = false
ij_shell_use_unix_line_separator = true
[{*.cjs,*.js}]
ij_continuation_indent_size = 4
ij_javascript_align_imports = false
ij_javascript_align_multiline_array_initializer_expression = false
ij_javascript_align_multiline_binary_operation = false
ij_javascript_align_multiline_chained_methods = false
ij_javascript_align_multiline_extends_list = false
ij_javascript_align_multiline_for = true
ij_javascript_align_multiline_parameters = true
ij_javascript_align_multiline_parameters_in_calls = false
ij_javascript_align_multiline_ternary_operation = false
ij_javascript_align_object_properties = 0
ij_javascript_align_union_types = false
ij_javascript_align_var_statements = 0
ij_javascript_array_initializer_new_line_after_left_brace = false
ij_javascript_array_initializer_right_brace_on_new_line = false
ij_javascript_array_initializer_wrap = off
ij_javascript_assignment_wrap = off
ij_javascript_binary_operation_sign_on_next_line = false
ij_javascript_binary_operation_wrap = off
ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
ij_javascript_blank_lines_after_imports = 1
ij_javascript_blank_lines_around_class = 1
ij_javascript_blank_lines_around_field = 0
ij_javascript_blank_lines_around_function = 1
ij_javascript_blank_lines_around_method = 1
ij_javascript_block_brace_style = end_of_line
ij_javascript_block_comment_add_space = false
ij_javascript_block_comment_at_first_column = true
ij_javascript_call_parameters_new_line_after_left_paren = false
ij_javascript_call_parameters_right_paren_on_new_line = false
ij_javascript_call_parameters_wrap = off
ij_javascript_catch_on_new_line = false
ij_javascript_chained_call_dot_on_new_line = true
ij_javascript_class_brace_style = end_of_line
ij_javascript_comma_on_new_line = false
ij_javascript_do_while_brace_force = never
ij_javascript_else_on_new_line = false
ij_javascript_enforce_trailing_comma = keep
ij_javascript_extends_keyword_wrap = off
ij_javascript_extends_list_wrap = off
ij_javascript_field_prefix = _
ij_javascript_file_name_style = relaxed
ij_javascript_finally_on_new_line = false
ij_javascript_for_brace_force = never
ij_javascript_for_statement_new_line_after_left_paren = false
ij_javascript_for_statement_right_paren_on_new_line = false
ij_javascript_for_statement_wrap = off
ij_javascript_force_quote_style = false
ij_javascript_force_semicolon_style = false
ij_javascript_function_expression_brace_style = end_of_line
ij_javascript_if_brace_force = never
ij_javascript_import_merge_members = global
ij_javascript_import_prefer_absolute_path = global
ij_javascript_import_sort_members = true
ij_javascript_import_sort_module_name = false
ij_javascript_import_use_node_resolution = true
ij_javascript_imports_wrap = on_every_item
ij_javascript_indent_case_from_switch = true
ij_javascript_indent_chained_calls = true
ij_javascript_indent_package_children = 0
ij_javascript_jsx_attribute_value = braces
ij_javascript_keep_blank_lines_in_code = 2
ij_javascript_keep_first_column_comment = true
ij_javascript_keep_indents_on_empty_lines = false
ij_javascript_keep_line_breaks = true
ij_javascript_keep_simple_blocks_in_one_line = false
ij_javascript_keep_simple_methods_in_one_line = false
ij_javascript_line_comment_add_space = true
ij_javascript_line_comment_at_first_column = false
ij_javascript_method_brace_style = end_of_line
ij_javascript_method_call_chain_wrap = off
ij_javascript_method_parameters_new_line_after_left_paren = false
ij_javascript_method_parameters_right_paren_on_new_line = false
ij_javascript_method_parameters_wrap = off
ij_javascript_object_literal_wrap = on_every_item
ij_javascript_parentheses_expression_new_line_after_left_paren = false
ij_javascript_parentheses_expression_right_paren_on_new_line = false
ij_javascript_place_assignment_sign_on_next_line = false
ij_javascript_prefer_as_type_cast = false
ij_javascript_prefer_explicit_types_function_expression_returns = false
ij_javascript_prefer_explicit_types_function_returns = false
ij_javascript_prefer_explicit_types_vars_fields = false
ij_javascript_prefer_parameters_wrap = false
ij_javascript_reformat_c_style_comments = false
ij_javascript_space_after_colon = true
ij_javascript_space_after_comma = true
ij_javascript_space_after_dots_in_rest_parameter = false
ij_javascript_space_after_generator_mult = true
ij_javascript_space_after_property_colon = true
ij_javascript_space_after_quest = true
ij_javascript_space_after_type_colon = true
ij_javascript_space_after_unary_not = false
ij_javascript_space_before_async_arrow_lparen = true
ij_javascript_space_before_catch_keyword = true
ij_javascript_space_before_catch_left_brace = true
ij_javascript_space_before_catch_parentheses = true
ij_javascript_space_before_class_lbrace = true
ij_javascript_space_before_class_left_brace = true
ij_javascript_space_before_colon = true
ij_javascript_space_before_comma = false
ij_javascript_space_before_do_left_brace = true
ij_javascript_space_before_else_keyword = true
ij_javascript_space_before_else_left_brace = true
ij_javascript_space_before_finally_keyword = true
ij_javascript_space_before_finally_left_brace = true
ij_javascript_space_before_for_left_brace = true
ij_javascript_space_before_for_parentheses = true
ij_javascript_space_before_for_semicolon = false
ij_javascript_space_before_function_left_parenth = true
ij_javascript_space_before_generator_mult = false
ij_javascript_space_before_if_left_brace = true
ij_javascript_space_before_if_parentheses = true
ij_javascript_space_before_method_call_parentheses = false
ij_javascript_space_before_method_left_brace = true
ij_javascript_space_before_method_parentheses = false
ij_javascript_space_before_property_colon = false
ij_javascript_space_before_quest = true
ij_javascript_space_before_switch_left_brace = true
ij_javascript_space_before_switch_parentheses = true
ij_javascript_space_before_try_left_brace = true
ij_javascript_space_before_type_colon = false
ij_javascript_space_before_unary_not = false
ij_javascript_space_before_while_keyword = true
ij_javascript_space_before_while_left_brace = true
ij_javascript_space_before_while_parentheses = true
ij_javascript_spaces_around_additive_operators = true
ij_javascript_spaces_around_arrow_function_operator = true
ij_javascript_spaces_around_assignment_operators = true
ij_javascript_spaces_around_bitwise_operators = true
ij_javascript_spaces_around_equality_operators = true
ij_javascript_spaces_around_logical_operators = true
ij_javascript_spaces_around_multiplicative_operators = true
ij_javascript_spaces_around_relational_operators = true
ij_javascript_spaces_around_shift_operators = true
ij_javascript_spaces_around_unary_operator = false
ij_javascript_spaces_within_array_initializer_brackets = false
ij_javascript_spaces_within_brackets = false
ij_javascript_spaces_within_catch_parentheses = false
ij_javascript_spaces_within_for_parentheses = false
ij_javascript_spaces_within_if_parentheses = false
ij_javascript_spaces_within_imports = false
ij_javascript_spaces_within_interpolation_expressions = false
ij_javascript_spaces_within_method_call_parentheses = false
ij_javascript_spaces_within_method_parentheses = false
ij_javascript_spaces_within_object_literal_braces = false
ij_javascript_spaces_within_object_type_braces = true
ij_javascript_spaces_within_parentheses = false
ij_javascript_spaces_within_switch_parentheses = false
ij_javascript_spaces_within_type_assertion = false
ij_javascript_spaces_within_union_types = true
ij_javascript_spaces_within_while_parentheses = false
ij_javascript_special_else_if_treatment = true
ij_javascript_ternary_operation_signs_on_next_line = false
ij_javascript_ternary_operation_wrap = off
ij_javascript_union_types_wrap = on_every_item
ij_javascript_use_chained_calls_group_indents = false
ij_javascript_use_double_quotes = true
ij_javascript_use_explicit_js_extension = auto
ij_javascript_use_path_mapping = always
ij_javascript_use_public_modifier = false
ij_javascript_use_semicolon_after_statement = true
ij_javascript_var_declaration_wrap = normal
ij_javascript_while_brace_force = never
ij_javascript_while_on_new_line = false
ij_javascript_wrap_comments = false
[{*.cjsx,*.coffee}]
indent_size = 2
tab_width = 2
ij_continuation_indent_size = 2
ij_coffeescript_align_function_body = false
ij_coffeescript_align_imports = false
ij_coffeescript_align_multiline_array_initializer_expression = true
ij_coffeescript_align_multiline_parameters = true
ij_coffeescript_align_multiline_parameters_in_calls = false
ij_coffeescript_align_object_properties = 0
ij_coffeescript_align_union_types = false
ij_coffeescript_align_var_statements = 0
ij_coffeescript_array_initializer_new_line_after_left_brace = false
ij_coffeescript_array_initializer_right_brace_on_new_line = false
ij_coffeescript_array_initializer_wrap = normal
ij_coffeescript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
ij_coffeescript_blank_lines_around_function = 1
ij_coffeescript_call_parameters_new_line_after_left_paren = false
ij_coffeescript_call_parameters_right_paren_on_new_line = false
ij_coffeescript_call_parameters_wrap = normal
ij_coffeescript_chained_call_dot_on_new_line = true
ij_coffeescript_comma_on_new_line = false
ij_coffeescript_enforce_trailing_comma = keep
ij_coffeescript_field_prefix = _
ij_coffeescript_file_name_style = relaxed
ij_coffeescript_force_quote_style = false
ij_coffeescript_force_semicolon_style = false
ij_coffeescript_function_expression_brace_style = end_of_line
ij_coffeescript_import_merge_members = global
ij_coffeescript_import_prefer_absolute_path = global
ij_coffeescript_import_sort_members = true
ij_coffeescript_import_sort_module_name = false
ij_coffeescript_import_use_node_resolution = true
ij_coffeescript_imports_wrap = on_every_item
ij_coffeescript_indent_chained_calls = true
ij_coffeescript_indent_package_children = 0
ij_coffeescript_jsx_attribute_value = braces
ij_coffeescript_keep_blank_lines_in_code = 2
ij_coffeescript_keep_first_column_comment = true
ij_coffeescript_keep_indents_on_empty_lines = false
ij_coffeescript_keep_line_breaks = true
ij_coffeescript_keep_simple_methods_in_one_line = false
ij_coffeescript_method_parameters_new_line_after_left_paren = false
ij_coffeescript_method_parameters_right_paren_on_new_line = false
ij_coffeescript_method_parameters_wrap = off
ij_coffeescript_object_literal_wrap = on_every_item
ij_coffeescript_prefer_as_type_cast = false
ij_coffeescript_prefer_explicit_types_function_expression_returns = false
ij_coffeescript_prefer_explicit_types_function_returns = false
ij_coffeescript_prefer_explicit_types_vars_fields = false
ij_coffeescript_reformat_c_style_comments = false
ij_coffeescript_space_after_comma = true
ij_coffeescript_space_after_dots_in_rest_parameter = false
ij_coffeescript_space_after_generator_mult = true
ij_coffeescript_space_after_property_colon = true
ij_coffeescript_space_after_type_colon = true
ij_coffeescript_space_after_unary_not = false
ij_coffeescript_space_before_async_arrow_lparen = true
ij_coffeescript_space_before_class_lbrace = true
ij_coffeescript_space_before_comma = false
ij_coffeescript_space_before_function_left_parenth = true
ij_coffeescript_space_before_generator_mult = false
ij_coffeescript_space_before_property_colon = false
ij_coffeescript_space_before_type_colon = false
ij_coffeescript_space_before_unary_not = false
ij_coffeescript_spaces_around_additive_operators = true
ij_coffeescript_spaces_around_arrow_function_operator = true
ij_coffeescript_spaces_around_assignment_operators = true
ij_coffeescript_spaces_around_bitwise_operators = true
ij_coffeescript_spaces_around_equality_operators = true
ij_coffeescript_spaces_around_logical_operators = true
ij_coffeescript_spaces_around_multiplicative_operators = true
ij_coffeescript_spaces_around_relational_operators = true
ij_coffeescript_spaces_around_shift_operators = true
ij_coffeescript_spaces_around_unary_operator = false
ij_coffeescript_spaces_within_array_initializer_braces = false
ij_coffeescript_spaces_within_array_initializer_brackets = false
ij_coffeescript_spaces_within_imports = false
ij_coffeescript_spaces_within_index_brackets = false
ij_coffeescript_spaces_within_interpolation_expressions = false
ij_coffeescript_spaces_within_method_call_parentheses = false
ij_coffeescript_spaces_within_method_parentheses = false
ij_coffeescript_spaces_within_object_braces = false
ij_coffeescript_spaces_within_object_literal_braces = false
ij_coffeescript_spaces_within_object_type_braces = true
ij_coffeescript_spaces_within_range_brackets = false
ij_coffeescript_spaces_within_type_assertion = false
ij_coffeescript_spaces_within_union_types = true
ij_coffeescript_union_types_wrap = on_every_item
ij_coffeescript_use_chained_calls_group_indents = false
ij_coffeescript_use_double_quotes = true
ij_coffeescript_use_explicit_js_extension = auto
ij_coffeescript_use_path_mapping = always
ij_coffeescript_use_public_modifier = false
ij_coffeescript_use_semicolon_after_statement = false
ij_coffeescript_var_declaration_wrap = normal
[{*.har,*.inputactions,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,jest.config}]
indent_size = 2
ij_json_keep_blank_lines_in_code = 0
ij_json_keep_indents_on_empty_lines = false
ij_json_keep_line_breaks = true
ij_json_space_after_colon = true
ij_json_space_after_comma = true
ij_json_space_before_colon = true
ij_json_space_before_comma = false
ij_json_spaces_within_braces = false
ij_json_spaces_within_brackets = false
ij_json_wrap_long_lines = false
[{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}]
ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
ij_html_align_attributes = true
ij_html_align_text = false
ij_html_attribute_wrap = normal
ij_html_block_comment_add_space = false
ij_html_block_comment_at_first_column = true
ij_html_do_not_align_children_of_min_lines = 0
ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p
ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot
ij_html_enforce_quotes = false
ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var
ij_html_keep_blank_lines = 2
ij_html_keep_indents_on_empty_lines = false
ij_html_keep_line_breaks = true
ij_html_keep_line_breaks_in_text = true
ij_html_keep_whitespaces = false
ij_html_keep_whitespaces_inside = span,pre,textarea
ij_html_line_comment_at_first_column = true
ij_html_new_line_after_last_attribute = never
ij_html_new_line_before_first_attribute = never
ij_html_quote_style = double
ij_html_remove_new_line_before_tags = br
ij_html_space_after_tag_name = false
ij_html_space_around_equality_in_attribute = false
ij_html_space_inside_empty_tag = false
ij_html_text_wrap = normal
[{*.markdown,*.md}]
ij_markdown_force_one_space_after_blockquote_symbol = true
ij_markdown_force_one_space_after_header_symbol = true
ij_markdown_force_one_space_after_list_bullet = true
ij_markdown_force_one_space_between_words = true
ij_markdown_insert_quote_arrows_on_wrap = true
ij_markdown_keep_indents_on_empty_lines = false
ij_markdown_keep_line_breaks_inside_text_blocks = true
ij_markdown_max_lines_around_block_elements = 1
ij_markdown_max_lines_around_header = 1
ij_markdown_max_lines_between_paragraphs = 1
ij_markdown_min_lines_around_block_elements = 1
ij_markdown_min_lines_around_header = 1
ij_markdown_min_lines_between_paragraphs = 1
ij_markdown_wrap_text_if_long = true
ij_markdown_wrap_text_inside_blockquotes = true
[{*.yaml,*.yml}]
indent_size = 2
ij_yaml_align_values_properties = do_not_align
ij_yaml_autoinsert_sequence_marker = true
ij_yaml_block_mapping_on_new_line = false
ij_yaml_indent_sequence_value = true
ij_yaml_keep_indents_on_empty_lines = false
ij_yaml_keep_line_breaks = true
ij_yaml_sequence_on_new_line = false
ij_yaml_space_before_colon = false
ij_yaml_spaces_within_braces = true
ij_yaml_spaces_within_brackets = true

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: "Need Help with Creating an Addon?"
url: "https://discord.gg/wusTQYbYTc"
about: "Join our discord and look for #nh-addon-discussion"

View File

@ -60,12 +60,6 @@ jobs:
- name: Copy Schemas
run: cp -rf NewHorizons/Schemas content/pages/
- name: Cache Site
uses: actions/cache@v2
with:
path: .m_cache
key: docs-cache
- name: Build Site
uses: VaultVulp/action-pipenv@v2.0.1

3
.gitignore vendored
View File

@ -411,7 +411,8 @@ NewHorizons/Properties/**
# Docs
docs/out/**
docs/content/schemas/**
docs/schemas/**
docs/content/pages/[Ss]chemas/**
docs/.m_cache/**
# Unity project
new-horizons-unity

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

View File

@ -9,19 +9,19 @@ namespace NewHorizons.Builder.Atmosphere
GameObject airGO = new GameObject("Air");
airGO.SetActive(false);
airGO.layer = 17;
airGO.transform.parent = sector?.transform ?? planetGO.transform;
airGO.transform.parent = sector?.transform ? sector.transform : planetGO.transform;
SphereCollider SC = airGO.AddComponent<SphereCollider>();
SC.isTrigger = true;
SC.radius = info.Scale;
SphereCollider sc = airGO.AddComponent<SphereCollider>();
sc.isTrigger = true;
sc.radius = info.Scale;
SimpleFluidVolume SFV = airGO.AddComponent<SimpleFluidVolume>();
SFV._layer = 5;
SFV._priority = 1;
SFV._density = 1.2f;
SFV._fluidType = FluidVolume.Type.AIR;
SFV._allowShipAutoroll = true;
SFV._disableOnStart = false;
SimpleFluidVolume sfv = airGO.AddComponent<SimpleFluidVolume>();
sfv._layer = 5;
sfv._priority = 1;
sfv._density = 1.2f;
sfv._fluidType = FluidVolume.Type.AIR;
sfv._allowShipAutoroll = true;
sfv._disableOnStart = false;
if (info.HasOxygen)
{
@ -30,10 +30,10 @@ namespace NewHorizons.Builder.Atmosphere
if (info.IsRaining)
{
VisorRainEffectVolume VREF = airGO.AddComponent<VisorRainEffectVolume>();
VREF._rainDirection = VisorRainEffectVolume.RainDirection.Radial;
VREF._layer = 0;
VREF._priority = 0;
var vref = airGO.AddComponent<VisorRainEffectVolume>();
vref._rainDirection = VisorRainEffectVolume.RainDirection.Radial;
vref._layer = 0;
vref._priority = 0;
AudioSource AS = airGO.AddComponent<AudioSource>();
AS.mute = false;
@ -49,10 +49,10 @@ namespace NewHorizons.Builder.Atmosphere
AS.spatialBlend = 0f;
AS.reverbZoneMix = 1f;
OWAudioSource OWAS = airGO.AddComponent<OWAudioSource>();
OWAS._audioLibraryClip = AudioType.GD_RainAmbient_LP;
OWAS.SetClipSelectionType(OWAudioSource.ClipSelectionOnPlay.RANDOM);
OWAS.SetTrack(OWAudioMixer.TrackName.Environment);
var owAudioSource = airGO.AddComponent<OWAudioSource>();
owAudioSource._audioLibraryClip = AudioType.GD_RainAmbient_LP;
owAudioSource.SetClipSelectionType(OWAudioSource.ClipSelectionOnPlay.RANDOM);
owAudioSource.SetTrack(OWAudioMixer.TrackName.Environment);
airGO.AddComponent<AudioVolume>();
}

View File

@ -4,6 +4,10 @@ namespace NewHorizons.Builder.Atmosphere
{
public static class AtmosphereBuilder
{
private static readonly int InnerRadius = Shader.PropertyToID("_InnerRadius");
private static readonly int OuterRadius = Shader.PropertyToID("_OuterRadius");
private static readonly int SkyColor = Shader.PropertyToID("_SkyColor");
public static void Make(GameObject planetGO, Sector sector, AtmosphereModule atmosphereModule, float surfaceSize)
{
GameObject atmoGO = new GameObject("Atmosphere");
@ -12,16 +16,15 @@ namespace NewHorizons.Builder.Atmosphere
if (atmosphereModule.UseAtmosphereShader)
{
GameObject atmo = GameObject.Instantiate(GameObject.Find("TimberHearth_Body/Atmosphere_TH/AtmoSphere"));
atmo.transform.parent = atmoGO.transform;
GameObject atmo = GameObject.Instantiate(GameObject.Find("TimberHearth_Body/Atmosphere_TH/AtmoSphere"), atmoGO.transform, true);
atmo.transform.position = planetGO.transform.TransformPoint(Vector3.zero);
atmo.transform.localScale = Vector3.one * atmosphereModule.Size * 1.2f;
foreach (var meshRenderer in atmo.GetComponentsInChildren<MeshRenderer>())
{
meshRenderer.material.SetFloat("_InnerRadius", atmosphereModule.Clouds != null ? atmosphereModule.Size : surfaceSize);
meshRenderer.material.SetFloat("_OuterRadius", atmosphereModule.Size * 1.2f);
meshRenderer.material.SetFloat(InnerRadius, atmosphereModule.Clouds != null ? atmosphereModule.Size : surfaceSize);
meshRenderer.material.SetFloat(OuterRadius, atmosphereModule.Size * 1.2f);
if (atmosphereModule.AtmosphereTint != null)
meshRenderer.material.SetColor("_SkyColor", atmosphereModule.AtmosphereTint.ToColor());
meshRenderer.material.SetColor(SkyColor, atmosphereModule.AtmosphereTint.ToColor());
}
atmo.SetActive(true);

View File

@ -11,6 +11,11 @@ namespace NewHorizons.Builder.Atmosphere
private static Shader _sphereShader = null;
private static Material[] _gdCloudMaterials;
private static GameObject _lightningPrefab;
private static readonly int Color1 = Shader.PropertyToID("_Color");
private static readonly int TintColor = Shader.PropertyToID("_TintColor");
private static readonly int MainTex = Shader.PropertyToID("_MainTex");
private static readonly int RampTex = Shader.PropertyToID("_RampTex");
private static readonly int CapTex = Shader.PropertyToID("_CapTex");
public static void Make(GameObject planetGO, Sector sector, AtmosphereModule atmo, IModBehaviour mod)
{
@ -39,8 +44,8 @@ namespace NewHorizons.Builder.Atmosphere
var bottomTSRTempArray = new Material[2];
bottomTSRTempArray[0] = new Material(bottomTSRMaterials[0]);
bottomTSRTempArray[0].SetColor("_Color", bottomColor);
bottomTSRTempArray[0].SetColor("_TintColor", bottomColor);
bottomTSRTempArray[0].SetColor(Color1, bottomColor);
bottomTSRTempArray[0].SetColor(TintColor, bottomColor);
bottomTSRTempArray[1] = new Material(bottomTSRMaterials[1]);
@ -133,7 +138,7 @@ namespace NewHorizons.Builder.Atmosphere
public static GameObject MakeTopClouds(GameObject rootObject, AtmosphereModule atmo, IModBehaviour mod)
{
Color cloudTint = atmo.Clouds.Tint == null ? Color.white : atmo.Clouds.Tint.ToColor();
Color cloudTint = atmo.Clouds.Tint?.ToColor() ?? Color.white;
Texture2D image, cap, ramp;
@ -188,12 +193,12 @@ namespace NewHorizons.Builder.Atmosphere
foreach (var material in topMR.sharedMaterials)
{
material.SetColor("_Color", cloudTint);
material.SetColor("_TintColor", cloudTint);
material.SetColor(Color1, cloudTint);
material.SetColor(TintColor, cloudTint);
material.SetTexture("_MainTex", image);
material.SetTexture("_RampTex", ramp);
material.SetTexture("_CapTex", cap);
material.SetTexture(MainTex, image);
material.SetTexture(RampTex, ramp);
material.SetTexture(CapTex, cap);
}
if (atmo.Clouds.Unlit)

View File

@ -4,6 +4,8 @@ namespace NewHorizons.Builder.Atmosphere
{
public static class VolumesBuilder
{
private static readonly int FogColor = Shader.PropertyToID("_FogColor");
public static void Make(GameObject planetGO, PlanetConfig config, float sphereOfInfluence)
{
var innerRadius = config.Base.SurfaceSize;
@ -42,7 +44,7 @@ namespace NewHorizons.Builder.Atmosphere
var cloudMaterial = new Material(gdRuleset._cloudMaterial);
if (config.Atmosphere?.Clouds?.Tint != null)
{
cloudMaterial.SetColor("_FogColor", config.Atmosphere.Clouds.Tint.ToColor32());
cloudMaterial.SetColor(FogColor, config.Atmosphere.Clouds.Tint.ToColor32());
}
ER._cloudMaterial = cloudMaterial;

View File

@ -9,6 +9,17 @@ namespace NewHorizons.Builder.Body
{
public static class FunnelBuilder
{
private static readonly int FogColor = Shader.PropertyToID("_FogColor");
private static readonly int EmissionColor = Shader.PropertyToID("_EmissionColor");
private static readonly int HeightScale = Shader.PropertyToID("_HeightScale");
private enum FunnelType
{
SAND,
WATER,
LAVA,
STAR
}
public static void Make(GameObject planetGO, ConstantForceDetector detector, OWRigidbody rigidbody, FunnelModule module)
{
@ -67,7 +78,7 @@ namespace NewHorizons.Builder.Body
materials[i] = new Material(waterMaterials[i]);
if (module.Tint != null)
{
materials[i].SetColor("_FogColor", module.Tint.ToColor());
materials[i].SetColor(FogColor, module.Tint.ToColor());
}
}
@ -114,7 +125,7 @@ namespace NewHorizons.Builder.Body
if (module.Tint != null)
{
lavaMaterial.SetColor("_EmissionColor", module.Tint.ToColor());
lavaMaterial.SetColor(EmissionColor, module.Tint.ToColor());
}
proxyGO.GetComponentInChildren<MeshRenderer>().material = lavaMaterial;
@ -122,13 +133,13 @@ namespace NewHorizons.Builder.Body
if (funnelType == FunnelType.Lava)
{
lavaMaterial.SetFloat("_HeightScale", 0);
lavaMaterial.SetFloat(HeightScale, 0);
AddDestructionVolumes(fluidVolume, DeathType.Lava);
}
else if (funnelType == FunnelType.Star)
{
lavaMaterial.renderQueue = 2999;
lavaMaterial.SetFloat("_HeightScale", 100000);
lavaMaterial.SetFloat(HeightScale, 100000);
AddDestructionVolumes(fluidVolume, DeathType.Energy);
}

View File

@ -43,9 +43,11 @@ namespace NewHorizons.Builder.Body
//if (PlanetShader == null) PlanetShader = Shader.Find("Standard");
var cubeSphereMR = cubeSphere.AddComponent<MeshRenderer>();
cubeSphereMR.material = new Material(PlanetShader);
cubeSphereMR.material.name = textureMap.name;
cubeSphereMR.material.mainTexture = textureMap;
var material = cubeSphereMR.material;
material = new Material(PlanetShader);
cubeSphereMR.material = material;
material.name = textureMap.name;
material.mainTexture = textureMap;
var cubeSphereMC = cubeSphere.AddComponent<MeshCollider>();
cubeSphereMC.sharedMesh = mesh;

View File

@ -6,6 +6,9 @@ namespace NewHorizons.Builder.Body
{
public static class LavaBuilder
{
private static readonly int HeightScale = Shader.PropertyToID("_HeightScale");
private static readonly int EmissionColor = Shader.PropertyToID("_EmissionColor");
public static void Make(GameObject planetGO, Sector sector, OWRigidbody rb, LavaModule module)
{
var heightScale = module.Size;
@ -28,8 +31,8 @@ namespace NewHorizons.Builder.Body
var lavaSphere = GameObject.Instantiate(GameObject.Find("VolcanicMoon_Body/MoltenCore_VM/LavaSphere"), moltenCore.transform);
lavaSphere.transform.localScale = Vector3.one;
lavaSphere.transform.name = "LavaSphere";
lavaSphere.GetComponent<MeshRenderer>().material.SetFloat("_HeightScale", heightScale);
if (module.Tint != null) lavaSphere.GetComponent<MeshRenderer>().material.SetColor("_EmissionColor", module.Tint.ToColor());
lavaSphere.GetComponent<MeshRenderer>().material.SetFloat(HeightScale, heightScale);
if (module.Tint != null) lavaSphere.GetComponent<MeshRenderer>().material.SetColor(EmissionColor, module.Tint.ToColor());
var sectorCullGroup = lavaSphere.GetComponent<SectorCullGroup>();
sectorCullGroup.SetSector(sector);
@ -40,8 +43,8 @@ namespace NewHorizons.Builder.Body
var proxyLavaSphere = moltenCoreProxy.transform.Find("LavaSphere (1)");
proxyLavaSphere.transform.localScale = Vector3.one;
proxyLavaSphere.name = "LavaSphere_Proxy";
proxyLavaSphere.GetComponent<MeshRenderer>().material.SetFloat("_HeightScale", heightScale);
if (module.Tint != null) proxyLavaSphere.GetComponent<MeshRenderer>().material.SetColor("_EmissionColor", module.Tint.ToColor());
proxyLavaSphere.GetComponent<MeshRenderer>().material.SetFloat(HeightScale, heightScale);
if (module.Tint != null) proxyLavaSphere.GetComponent<MeshRenderer>().material.SetColor(EmissionColor, module.Tint.ToColor());
var sectorProxy = moltenCoreProxy.GetComponent<SectorProxy>();
sectorProxy._renderers = new List<Renderer> { proxyLavaSphere.GetComponent<MeshRenderer>() };

View File

@ -19,6 +19,12 @@ namespace NewHorizons.Builder.Body
private static readonly string _blackHolePath = "TowerTwin_Body/Sector_TowerTwin/Sector_Tower_HGT/Interactables_Tower_HGT/Interactables_Tower_TT/Prefab_NOM_WarpTransmitter (1)/BlackHole/BlackHoleSingularity";
private static readonly string _whiteHolePath = "TowerTwin_Body/Sector_TowerTwin/Sector_Tower_HGT/Interactables_Tower_HGT/Interactables_Tower_CT/Prefab_NOM_WarpTransmitter/WhiteHole/WhiteHoleSingularity";
private static readonly int EmissionColor = Shader.PropertyToID("_EmissionColor");
private static readonly int Radius = Shader.PropertyToID("_Radius");
private static readonly int MaxDistortRadius = Shader.PropertyToID("_MaxDistortRadius");
private static readonly int MassScale = Shader.PropertyToID("_MassScale");
private static readonly int DistortFadeDist = Shader.PropertyToID("_DistortFadeDist");
private static readonly int Color1 = Shader.PropertyToID("_Color");
public static void Make(GameObject planetGO, NewHorizonsBody body)
@ -71,7 +77,7 @@ namespace NewHorizons.Builder.Body
if (realSize < body.Config.Lava.Size) realSize = body.Config.Lava.Size;
var material = new Material(lavaMaterial);
if (body.Config.Lava.Tint != null) material.SetColor("_EmissionColor", body.Config.Lava.Tint.ToColor());
if (body.Config.Lava.Tint != null) material.SetColor(EmissionColor, body.Config.Lava.Tint.ToColor());
sphere.GetComponent<MeshRenderer>().material = material;
}
if (body.Config.Water != null)
@ -185,10 +191,10 @@ namespace NewHorizons.Builder.Body
var meshRenderer = blackHoleRender.AddComponent<MeshRenderer>();
meshRenderer.material = new Material(blackHoleShader);
meshRenderer.material.SetFloat("_Radius", size * 0.4f);
meshRenderer.material.SetFloat("_MaxDistortRadius", size * 0.95f);
meshRenderer.material.SetFloat("_MassScale", 1);
meshRenderer.material.SetFloat("_DistortFadeDist", size * 0.55f);
meshRenderer.material.SetFloat(Radius, size * 0.4f);
meshRenderer.material.SetFloat(MaxDistortRadius, size * 0.95f);
meshRenderer.material.SetFloat(MassScale, 1);
meshRenderer.material.SetFloat(DistortFadeDist, size * 0.55f);
blackHoleRender.SetActive(true);
}
@ -210,10 +216,10 @@ namespace NewHorizons.Builder.Body
var meshRenderer = whiteHoleRenderer.AddComponent<MeshRenderer>();
meshRenderer.material = new Material(whiteHoleShader);
meshRenderer.sharedMaterial.SetFloat("_Radius", size * 0.4f);
meshRenderer.sharedMaterial.SetFloat("_DistortFadeDist", size);
meshRenderer.sharedMaterial.SetFloat("_MaxDistortRadius", size * 2.8f);
meshRenderer.sharedMaterial.SetColor("_Color", new Color(1.88f, 1.88f, 1.88f, 1f));
meshRenderer.sharedMaterial.SetFloat(Radius, size * 0.4f);
meshRenderer.sharedMaterial.SetFloat(DistortFadeDist, size);
meshRenderer.sharedMaterial.SetFloat(MaxDistortRadius, size * 2.8f);
meshRenderer.sharedMaterial.SetColor(Color1, new Color(1.88f, 1.88f, 1.88f, 1f));
whiteHoleRenderer.SetActive(true);
}

View File

@ -17,6 +17,7 @@ namespace NewHorizons.Builder.Body
public static Shader RingShader1Pixel;
public static Shader UnlitRingShader;
public static Shader UnlitRingShader1Pixel;
private static readonly int InnerRadius = Shader.PropertyToID("_InnerRadius");
public static GameObject Make(GameObject planetGO, Sector sector, RingModule ring, IModBehaviour mod)
{
@ -106,7 +107,7 @@ namespace NewHorizons.Builder.Body
if (texture.width == 1)
{
mat = new Material(ring.Unlit ? UnlitRingShader1Pixel : RingShader1Pixel);
mat.SetFloat("_InnerRadius", 0);
mat.SetFloat(InnerRadius, 0);
}
ringMR.receiveShadows = !ring.Unlit;

View File

@ -12,6 +12,11 @@ namespace NewHorizons.Builder.Body
private static Shader blackHoleShader = null;
private static Shader whiteHoleShader = null;
private static readonly int Radius = Shader.PropertyToID("_Radius");
private static readonly int MaxDistortRadius = Shader.PropertyToID("_MaxDistortRadius");
private static readonly int MassScale = Shader.PropertyToID("_MassScale");
private static readonly int DistortFadeDist = Shader.PropertyToID("_DistortFadeDist");
private static readonly int Color1 = Shader.PropertyToID("_Color");
public static void Make(GameObject go, Sector sector, OWRigidbody OWRB, PlanetConfig config)
{
@ -88,10 +93,10 @@ namespace NewHorizons.Builder.Body
var meshRenderer = blackHoleRender.AddComponent<MeshRenderer>();
if (blackHoleShader == null) blackHoleShader = GameObject.Find("BrittleHollow_Body/BlackHole_BH/BlackHoleRenderer").GetComponent<MeshRenderer>().sharedMaterial.shader;
meshRenderer.material = new Material(blackHoleShader);
meshRenderer.material.SetFloat("_Radius", size * 0.4f);
meshRenderer.material.SetFloat("_MaxDistortRadius", size * 0.95f);
meshRenderer.material.SetFloat("_MassScale", 1);
meshRenderer.material.SetFloat("_DistortFadeDist", size * 0.55f);
meshRenderer.material.SetFloat(Radius, size * 0.4f);
meshRenderer.material.SetFloat(MaxDistortRadius, size * 0.95f);
meshRenderer.material.SetFloat(MassScale, 1);
meshRenderer.material.SetFloat(DistortFadeDist, size * 0.55f);
if (makeAudio)
{
@ -159,11 +164,11 @@ namespace NewHorizons.Builder.Body
var meshRenderer = whiteHoleRenderer.AddComponent<MeshRenderer>();
if (whiteHoleShader == null) whiteHoleShader = GameObject.Find("WhiteHole_Body/WhiteHoleVisuals/Singularity").GetComponent<MeshRenderer>().sharedMaterial.shader;
meshRenderer.material = new Material(whiteHoleShader);
meshRenderer.sharedMaterial.SetFloat("_Radius", size * 0.4f);
meshRenderer.sharedMaterial.SetFloat("_DistortFadeDist", size);
meshRenderer.sharedMaterial.SetFloat("_MaxDistortRadius", size * 2.8f);
meshRenderer.sharedMaterial.SetFloat("_MassScale", -1);
meshRenderer.sharedMaterial.SetColor("_Color", new Color(1.88f, 1.88f, 1.88f, 1f));
meshRenderer.sharedMaterial.SetFloat(Radius, size * 0.4f);
meshRenderer.sharedMaterial.SetFloat(DistortFadeDist, size);
meshRenderer.sharedMaterial.SetFloat(MaxDistortRadius, size * 2.8f);
meshRenderer.sharedMaterial.SetFloat(MassScale, -1);
meshRenderer.sharedMaterial.SetColor(Color1, new Color(1.88f, 1.88f, 1.88f, 1f));
var ambientLight = GameObject.Instantiate(GameObject.Find("WhiteHole_Body/WhiteHoleVisuals/AmbientLight_WH"));
ambientLight.transform.parent = whiteHole.transform;

View File

@ -11,6 +11,12 @@ namespace NewHorizons.Builder.Body
{
public const float OuterRadiusRatio = 1.5f;
private static Texture2D _colorOverTime;
private static readonly int ColorRamp = Shader.PropertyToID("_ColorRamp");
private static readonly int SkyColor = Shader.PropertyToID("_SkyColor");
private static readonly int AtmosFar = Shader.PropertyToID("_AtmosFar");
private static readonly int AtmosNear = Shader.PropertyToID("_AtmosNear");
private static readonly int InnerRadius = Shader.PropertyToID("_InnerRadius");
private static readonly int OuterRadius = Shader.PropertyToID("_OuterRadius");
public static StarController Make(GameObject planetGO, Sector sector, StarModule starModule)
{
@ -40,11 +46,11 @@ namespace NewHorizons.Builder.Body
sunAtmosphere.transform.Find("AtmoSphere").transform.localScale = Vector3.one;
foreach (var lod in sunAtmosphere.transform.Find("AtmoSphere").GetComponentsInChildren<MeshRenderer>())
{
lod.material.SetColor("_SkyColor", starModule.Tint.ToColor());
lod.material.SetColor("_AtmosFar", starModule.Tint.ToColor());
lod.material.SetColor("_AtmosNear", starModule.Tint.ToColor());
lod.material.SetFloat("_InnerRadius", starModule.Size);
lod.material.SetFloat("_OuterRadius", starModule.Size * OuterRadiusRatio);
lod.material.SetColor(SkyColor, starModule.Tint.ToColor());
lod.material.SetColor(AtmosFar, starModule.Tint.ToColor());
lod.material.SetColor(AtmosNear, starModule.Tint.ToColor());
lod.material.SetFloat(InnerRadius, starModule.Size);
lod.material.SetFloat(OuterRadius, starModule.Size * OuterRadiusRatio);
}
}
fog.transform.localScale = Vector3.one;
@ -85,15 +91,6 @@ namespace NewHorizons.Builder.Body
Color lightColour = light.color;
if (starModule.LightTint != null) lightColour = starModule.LightTint.ToColor();
if (lightColour == null && starModule.Tint != null)
{
// Lighten it a bit
var r = Mathf.Clamp01(starModule.Tint.R * 1.5f);
var g = Mathf.Clamp01(starModule.Tint.G * 1.5f);
var b = Mathf.Clamp01(starModule.Tint.B * 1.5f);
lightColour = new Color(r, g, b);
}
if (lightColour != null) light.color = (Color)lightColour;
light.color = lightColour;
ambientLight.color = lightColour;
@ -218,7 +215,7 @@ namespace NewHorizons.Builder.Body
darkenedColor = new Color(endColour.r * mod, endColour.g * mod, endColour.b * mod);
}
surface.sharedMaterial.SetTexture("_ColorRamp", ImageUtilities.LerpGreyscaleImage(_colorOverTime, adjustedColour, darkenedColor));
surface.sharedMaterial.SetTexture(ColorRamp, ImageUtilities.LerpGreyscaleImage(_colorOverTime, adjustedColour, darkenedColor));
}
return starGO;
@ -240,7 +237,7 @@ namespace NewHorizons.Builder.Body
var supernovaMaterial = new Material(supernova._supernovaMaterial);
var ramp = ImageUtilities.LerpGreyscaleImage(ImageUtilities.GetTexture(Main.Instance, "AssetBundle/Effects_SUN_Supernova_d.png"), Color.white, colour);
supernovaMaterial.SetTexture("_ColorRamp", ramp);
supernovaMaterial.SetTexture(ColorRamp, ramp);
supernova._supernovaMaterial = supernovaMaterial;
// Motes

View File

@ -9,6 +9,9 @@ namespace NewHorizons.Builder.Body
{
public static class WaterBuilder
{
private static readonly int Radius = Shader.PropertyToID("_Radius");
private static readonly int Radius2 = Shader.PropertyToID("_Radius2");
public static void Make(GameObject planetGO, Sector sector, OWRigidbody rb, WaterModule module)
{
var waterSize = module.Size;
@ -101,8 +104,8 @@ namespace NewHorizons.Builder.Body
}
else
{
fogGO.GetComponent<MeshRenderer>().material.SetFloat("_Radius", module.Size);
fogGO.GetComponent<MeshRenderer>().material.SetFloat("_Radius2", module.Size / 2f);
fogGO.GetComponent<MeshRenderer>().material.SetFloat(Radius, module.Size);
fogGO.GetComponent<MeshRenderer>().material.SetFloat(Radius2, module.Size / 2f);
}
// TODO: make LOD work

View File

@ -1,213 +1,223 @@
using NewHorizons.External.Configs;
using NewHorizons.External.Modules;
using NewHorizons.Handlers;
using NewHorizons.Utility;
using OWML.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.Props
{
public static class DetailBuilder
{
public static void Make(GameObject go, Sector sector, PlanetConfig config, IModBehaviour mod, string uniqueModName, PropModule.DetailInfo detail)
{
GameObject detailGO = null;
if (detail.assetBundle != null)
{
var prefab = AssetBundleUtilities.LoadPrefab(detail.assetBundle, detail.path, mod);
detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
}
else if (detail.objFilePath != null)
{
try
{
var prefab = mod.ModHelper.Assets.Get3DObject(detail.objFilePath, detail.mtlFilePath);
AssetBundleUtilities.ReplaceShaders(prefab);
prefab.SetActive(false);
detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
}
catch (Exception e)
{
Logger.LogError($"Could not load 3d object {detail.objFilePath} with texture {detail.mtlFilePath} : {e.Message}");
}
}
else detailGO = MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
if (detailGO != null && detail.removeChildren != null)
{
foreach (var childPath in detail.removeChildren)
{
var childObj = detailGO.transform.Find(childPath);
if (childObj != null) childObj.gameObject.SetActive(false);
else Logger.LogWarning($"Couldn't find {childPath}");
}
}
if (detailGO != null && detail.removeComponents)
{
// Just swap all the children to a new game object
var newDetailGO = new GameObject(detailGO.name);
newDetailGO.transform.position = detailGO.transform.position;
newDetailGO.transform.parent = detailGO.transform.parent;
// Can't modify parents while looping through children bc idk
var children = new List<Transform>();
foreach (Transform child in detailGO.transform)
{
children.Add(child);
}
foreach (var child in children)
{
child.parent = newDetailGO.transform;
}
GameObject.Destroy(detailGO);
detailGO = newDetailGO;
}
}
public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal)
{
var prefab = SearchUtilities.Find(propToClone);
if (prefab == null) Logger.LogError($"Couldn't find detail {propToClone}");
return MakeDetail(go, sector, prefab, position, rotation, scale, alignWithNormal);
}
public static GameObject MakeDetail(GameObject planetGO, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal)
{
if (prefab == null) return null;
GameObject prop = prefab.InstantiateInactive();
prop.transform.parent = sector?.transform ?? planetGO.transform;
prop.SetActive(false);
if (sector != null) sector.OnOccupantEnterSector += (SectorDetector sd) => OWAssetHandler.OnOccupantEnterSector(prop, sd, sector);
OWAssetHandler.LoadObject(prop);
foreach (var component in prop.GetComponents<Component>().Concat(prop.GetComponentsInChildren<Component>()))
{
// Enable all children or something
var enabledField = component?.GetType()?.GetField("enabled");
if (enabledField != null && enabledField.FieldType == typeof(bool)) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => enabledField.SetValue(component, true));
// Fix a bunch of sector stuff
if (sector != null)
{
if (component is Sector)
{
(component as Sector)._parentSector = sector;
}
// TODO: Make this work or smthng
if (component is GhostIK) (component as GhostIK).enabled = false;
if (component is GhostEffects) (component as GhostEffects).enabled = false;
if (component is DarkMatterVolume)
{
var probeVisuals = component.gameObject.transform.Find("ProbeVisuals");
if (probeVisuals != null) probeVisuals.gameObject.SetActive(true);
}
if (component is SectoredMonoBehaviour)
{
(component as SectoredMonoBehaviour).SetSector(sector);
}
else
{
var sectorField = component?.GetType()?.GetField("_sector");
if (sectorField != null && sectorField.FieldType == typeof(Sector)) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => sectorField.SetValue(component, sector));
}
if (component is AnglerfishController)
{
try
{
(component as AnglerfishController)._chaseSpeed += OWPhysics.CalculateOrbitVelocity(planetGO.GetAttachedOWRigidbody(), planetGO.GetComponent<AstroObject>().GetPrimaryBody().GetAttachedOWRigidbody()).magnitude;
}
catch (Exception e)
{
Logger.LogError($"Couldn't update AnglerFish chase speed: {e.Message}");
}
}
// Fix slide reel
if (component is SlideCollectionContainer)
{
sector.OnOccupantEnterSector.AddListener((_) => (component as SlideCollectionContainer).LoadStreamingTextures());
}
if (component is OWItemSocket)
{
(component as OWItemSocket)._sector = sector;
}
}
else
{
// Remove things that require sectors. Will just keep extending this as things pop up
if (component is FogLight || component is SectoredMonoBehaviour)
{
GameObject.DestroyImmediate(component);
continue;
}
}
// Fix a bunch of stuff when done loading
Main.Instance.ModHelper.Events.Unity.RunWhen(() => Main.IsSystemReady, () =>
{
try
{
if (component is Animator) (component as Animator).enabled = true;
else if (component is Collider) (component as Collider).enabled = true;
else if (component is Renderer) (component as Renderer).enabled = true;
else if (component is Shape) (component as Shape).enabled = true;
// If it's not a moving anglerfish make sure the anim controller is regular
else if (component is AnglerfishAnimController && component.GetComponentInParent<AnglerfishController>() == null)
{
Logger.Log("Enabling anglerfish animation");
var angler = (component as AnglerfishAnimController);
// Remove any reference to its angler
if (angler._anglerfishController)
{
angler._anglerfishController.OnChangeAnglerState -= angler.OnChangeAnglerState;
angler._anglerfishController.OnAnglerTurn -= angler.OnAnglerTurn;
angler._anglerfishController.OnAnglerSuspended -= angler.OnAnglerSuspended;
angler._anglerfishController.OnAnglerUnsuspended -= angler.OnAnglerUnsuspended;
}
angler.enabled = true;
angler.OnChangeAnglerState(AnglerfishController.AnglerState.Lurking);
}
}
catch (Exception e)
{
Logger.LogWarning($"Exception when modifying component [{component.GetType().Name}] on [{planetGO.name}] : {e.Message}, {e.StackTrace}");
}
});
}
prop.transform.position = position == null ? planetGO.transform.position : planetGO.transform.TransformPoint((Vector3)position);
Quaternion rot = rotation == null ? Quaternion.identity : Quaternion.Euler((Vector3)rotation);
if (alignWithNormal)
{
// Apply the rotation after aligning it with normal
var up = planetGO.transform.InverseTransformPoint(prop.transform.position).normalized;
prop.transform.rotation = Quaternion.FromToRotation(Vector3.up, up);
prop.transform.rotation *= rot;
}
else
{
prop.transform.rotation = planetGO.transform.TransformRotation(rot);
}
prop.transform.localScale = scale != 0 ? Vector3.one * scale : prefab.transform.localScale;
prop.SetActive(true);
return prop;
}
}
}
using NewHorizons.External.Configs;
using NewHorizons.External.Modules;
using NewHorizons.Handlers;
using NewHorizons.Utility;
using OWML.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.Props
{
public static class DetailBuilder
{
private static Dictionary<PropModule.DetailInfo, GameObject> detailInfoToCorrespondingSpawnedGameObject = new Dictionary<PropModule.DetailInfo, GameObject>();
public static GameObject GetSpawnedGameObjectByDetailInfo(PropModule.DetailInfo detail)
{
if (!detailInfoToCorrespondingSpawnedGameObject.ContainsKey(detail)) return null;
return detailInfoToCorrespondingSpawnedGameObject[detail];
}
public static void Make(GameObject go, Sector sector, PlanetConfig config, IModBehaviour mod, string uniqueModName, PropModule.DetailInfo detail)
{
GameObject detailGO = null;
if (detail.assetBundle != null)
{
var prefab = AssetBundleUtilities.LoadPrefab(detail.assetBundle, detail.path, mod);
detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
}
else if (detail.objFilePath != null)
{
try
{
var prefab = mod.ModHelper.Assets.Get3DObject(detail.objFilePath, detail.mtlFilePath);
AssetBundleUtilities.ReplaceShaders(prefab);
prefab.SetActive(false);
detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
}
catch (Exception e)
{
Logger.LogError($"Could not load 3d object {detail.objFilePath} with texture {detail.mtlFilePath} : {e.Message}");
}
}
else detailGO = MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
if (detailGO != null && detail.removeChildren != null)
{
foreach (var childPath in detail.removeChildren)
{
var childObj = detailGO.transform.Find(childPath);
if (childObj != null) childObj.gameObject.SetActive(false);
else Logger.LogWarning($"Couldn't find {childPath}");
}
}
if (detailGO != null && detail.removeComponents)
{
// Just swap all the children to a new game object
var newDetailGO = new GameObject(detailGO.name);
newDetailGO.transform.position = detailGO.transform.position;
newDetailGO.transform.parent = detailGO.transform.parent;
// Can't modify parents while looping through children bc idk
var children = new List<Transform>();
foreach (Transform child in detailGO.transform)
{
children.Add(child);
}
foreach (var child in children)
{
child.parent = newDetailGO.transform;
}
GameObject.Destroy(detailGO);
detailGO = newDetailGO;
}
detailInfoToCorrespondingSpawnedGameObject[detail] = detailGO;
}
public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal)
{
var prefab = SearchUtilities.Find(propToClone);
if (prefab == null) Logger.LogError($"Couldn't find detail {propToClone}");
return MakeDetail(go, sector, prefab, position, rotation, scale, alignWithNormal);
}
public static GameObject MakeDetail(GameObject planetGO, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal)
{
if (prefab == null) return null;
GameObject prop = prefab.InstantiateInactive();
prop.transform.parent = sector?.transform ?? planetGO.transform;
prop.SetActive(false);
if (sector != null) sector.OnOccupantEnterSector += (SectorDetector sd) => OWAssetHandler.OnOccupantEnterSector(prop, sd, sector);
OWAssetHandler.LoadObject(prop);
foreach (var component in prop.GetComponents<Component>().Concat(prop.GetComponentsInChildren<Component>()))
{
// Enable all children or something
var enabledField = component?.GetType()?.GetField("enabled");
if (enabledField != null && enabledField.FieldType == typeof(bool)) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => enabledField.SetValue(component, true));
// Fix a bunch of sector stuff
if (sector != null)
{
if (component is Sector)
{
(component as Sector)._parentSector = sector;
}
// TODO: Make this work or smthng
if (component is GhostIK) (component as GhostIK).enabled = false;
if (component is GhostEffects) (component as GhostEffects).enabled = false;
if (component is DarkMatterVolume)
{
var probeVisuals = component.gameObject.transform.Find("ProbeVisuals");
if (probeVisuals != null) probeVisuals.gameObject.SetActive(true);
}
if (component is SectoredMonoBehaviour)
{
(component as SectoredMonoBehaviour).SetSector(sector);
}
else
{
var sectorField = component?.GetType()?.GetField("_sector");
if (sectorField != null && sectorField.FieldType == typeof(Sector)) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => sectorField.SetValue(component, sector));
}
if (component is AnglerfishController)
{
try
{
(component as AnglerfishController)._chaseSpeed += OWPhysics.CalculateOrbitVelocity(planetGO.GetAttachedOWRigidbody(), planetGO.GetComponent<AstroObject>().GetPrimaryBody().GetAttachedOWRigidbody()).magnitude;
}
catch (Exception e)
{
Logger.LogError($"Couldn't update AnglerFish chase speed: {e.Message}");
}
}
// Fix slide reel
if (component is SlideCollectionContainer)
{
sector.OnOccupantEnterSector.AddListener((_) => (component as SlideCollectionContainer).LoadStreamingTextures());
}
if (component is OWItemSocket)
{
(component as OWItemSocket)._sector = sector;
}
}
else
{
// Remove things that require sectors. Will just keep extending this as things pop up
if (component is FogLight || component is SectoredMonoBehaviour)
{
GameObject.DestroyImmediate(component);
continue;
}
}
// Fix a bunch of stuff when done loading
Main.Instance.ModHelper.Events.Unity.RunWhen(() => Main.IsSystemReady, () =>
{
try
{
if (component is Animator) (component as Animator).enabled = true;
else if (component is Collider) (component as Collider).enabled = true;
else if (component is Renderer) (component as Renderer).enabled = true;
else if (component is Shape) (component as Shape).enabled = true;
// If it's not a moving anglerfish make sure the anim controller is regular
else if (component is AnglerfishAnimController && component.GetComponentInParent<AnglerfishController>() == null)
{
Logger.Log("Enabling anglerfish animation");
var angler = (component as AnglerfishAnimController);
// Remove any reference to its angler
if (angler._anglerfishController)
{
angler._anglerfishController.OnChangeAnglerState -= angler.OnChangeAnglerState;
angler._anglerfishController.OnAnglerTurn -= angler.OnAnglerTurn;
angler._anglerfishController.OnAnglerSuspended -= angler.OnAnglerSuspended;
angler._anglerfishController.OnAnglerUnsuspended -= angler.OnAnglerUnsuspended;
}
angler.enabled = true;
angler.OnChangeAnglerState(AnglerfishController.AnglerState.Lurking);
}
}
catch (Exception e)
{
Logger.LogWarning($"Exception when modifying component [{component.GetType().Name}] on [{planetGO.name}] : {e.Message}, {e.StackTrace}");
}
});
}
prop.transform.position = position == null ? planetGO.transform.position : planetGO.transform.TransformPoint((Vector3)position);
Quaternion rot = rotation == null ? Quaternion.identity : Quaternion.Euler((Vector3)rotation);
if (alignWithNormal)
{
// Apply the rotation after aligning it with normal
var up = planetGO.transform.InverseTransformPoint(prop.transform.position).normalized;
prop.transform.rotation = Quaternion.FromToRotation(Vector3.up, up);
prop.transform.rotation *= rot;
}
else
{
prop.transform.rotation = planetGO.transform.TransformRotation(rot);
}
prop.transform.localScale = scale != 0 ? Vector3.one * scale : prefab.transform.localScale;
prop.SetActive(true);
return prop;
}
}
}

View File

@ -12,6 +12,8 @@ namespace NewHorizons.Builder.Props
{
private static GameObject _slideReelPrefab;
private static GameObject _autoPrefab;
private static readonly int EmissionMap = Shader.PropertyToID("_EmissionMap");
public static void Make(GameObject go, Sector sector, PropModule.ProjectionInfo info, IModBehaviour mod)
{
switch (info.type)
@ -99,9 +101,9 @@ namespace NewHorizons.Builder.Props
// Now put together the textures into a 4x4 thing for the materials
var reelTexture = ImageUtilities.MakeReelTexture(textures);
slidesBack.material.mainTexture = reelTexture;
slidesBack.material.SetTexture("_EmissionMap", reelTexture);
slidesBack.material.SetTexture(EmissionMap, reelTexture);
slidesFront.material.mainTexture = reelTexture;
slidesFront.material.SetTexture("_EmissionMap", reelTexture);
slidesFront.material.SetTexture(EmissionMap, reelTexture);
slideReelObj.SetActive(true);
}
@ -156,7 +158,7 @@ namespace NewHorizons.Builder.Props
// Change the picture on the lens
var lens = projectorObj.transform.Find("Spotlight/Prop_IP_SingleSlideProjector/Projector_Lens").GetComponent<MeshRenderer>();
lens.materials[1].mainTexture = slideCollection.slides[0]._textureOverride;
lens.materials[1].SetTexture("_EmissionMap", slideCollection.slides[0]._textureOverride);
lens.materials[1].SetTexture(EmissionMap, slideCollection.slides[0]._textureOverride);
projectorObj.SetActive(true);
}

View File

@ -9,39 +9,67 @@ namespace NewHorizons.Builder.Props
{
public static class TornadoBuilder
{
private static GameObject upPrefab;
private static GameObject downPrefab;
private static GameObject soundPrefab;
private static GameObject _upPrefab;
private static GameObject _downPrefab;
private static GameObject _hurricanePrefab;
private static GameObject _soundPrefab;
private static Texture2D _mainTexture;
private static Texture2D _detailTexture;
private static readonly int DetailColor = Shader.PropertyToID("_DetailColor");
private static readonly int TintColor = Shader.PropertyToID("_TintColor");
private static readonly int DetailTex = Shader.PropertyToID("_DetailTex");
private static readonly int MainTex = Shader.PropertyToID("_MainTex");
private static readonly int FresnelColor = Shader.PropertyToID("_FresnelColor");
public static void Make(GameObject planetGO, Sector sector, PropModule.TornadoInfo info, bool hasClouds)
{
if (upPrefab == null)
if (_upPrefab == null)
{
upPrefab = GameObject.Find("BrittleHollow_Body/Sector_BH/Sector_SouthHemisphere/Sector_SouthPole/Sector_Observatory/Interactables_Observatory/MockUpTornado").InstantiateInactive();
upPrefab.name = "Tornado_Up_Prefab";
_upPrefab = GameObject.Find("BrittleHollow_Body/Sector_BH/Sector_SouthHemisphere/Sector_SouthPole/Sector_Observatory/Interactables_Observatory/MockUpTornado").InstantiateInactive();
_upPrefab.name = "Tornado_Up_Prefab";
}
if (downPrefab == null)
if (_downPrefab == null)
{
downPrefab = GameObject.Find("BrittleHollow_Body/Sector_BH/Sector_SouthHemisphere/Sector_SouthPole/Sector_Observatory/Interactables_Observatory/MockDownTornado").InstantiateInactive();
downPrefab.name = "Tornado_Down_Prefab";
_downPrefab = GameObject.Find("BrittleHollow_Body/Sector_BH/Sector_SouthHemisphere/Sector_SouthPole/Sector_Observatory/Interactables_Observatory/MockDownTornado").InstantiateInactive();
_downPrefab.name = "Tornado_Down_Prefab";
}
if (soundPrefab == null)
if (_hurricanePrefab == null)
{
soundPrefab = GameObject.Find("GiantsDeep_Body/Sector_GD/Sector_GDInterior/Tornadoes_GDInterior/SouthernTornadoes/DownTornado_Pivot/DownTornado/AudioRail").InstantiateInactive();
soundPrefab.name = "AudioRail_Prefab";
_hurricanePrefab = GameObject.Find("GiantsDeep_Body/Sector_GD/Sector_GDInterior/Tornadoes_GDInterior/Hurricane/").InstantiateInactive();
// For some reason they put the hurricane at the origin and offset all its children (450)
// Increasing by 40 will keep the bottom above the ground
foreach (Transform child in _hurricanePrefab.transform)
{
child.localPosition += new Vector3(0, 40 - 450, 0);
}
foreach (var renderer in _hurricanePrefab.GetComponentsInChildren<Renderer>())
{
renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
}
}
if (_soundPrefab == null)
{
_soundPrefab = GameObject.Find("GiantsDeep_Body/Sector_GD/Sector_GDInterior/Tornadoes_GDInterior/SouthernTornadoes/DownTornado_Pivot/DownTornado/AudioRail").InstantiateInactive();
_soundPrefab.name = "AudioRail_Prefab";
}
if (_mainTexture == null)
{
_mainTexture = ImageUtilities.GetTexture(Main.Instance, "AssetBundle/Tornado_BH_Cyclone_02_d.png");
}
if (_detailTexture == null)
{
_detailTexture = ImageUtilities.GetTexture(Main.Instance, "AssetBundle/Tornado_BH_CycloneDetail_d.png");
}
float elevation;
Vector3 position;
if (info.position != null)
{
position = info.position ?? Random.onUnitSphere * info.elevation;
elevation = position.magnitude;
}
else if (info.elevation != 0)
{
position = Random.onUnitSphere * info.elevation;
elevation = info.elevation;
}
else
{
@ -49,13 +77,19 @@ namespace NewHorizons.Builder.Props
return;
}
var tornadoGO = info.downwards ? downPrefab.InstantiateInactive() : upPrefab.InstantiateInactive();
if (info.type.ToLower() == "hurricane") MakeHurricane(planetGO, sector, info, position, hasClouds);
else MakeTornado(planetGO, sector, info, position, info.type.ToLower() == "downwards");
}
private static void MakeTornado(GameObject planetGO, Sector sector, PropModule.TornadoInfo info, Vector3 position, bool downwards)
{
var tornadoGO = downwards ? _downPrefab.InstantiateInactive() : _upPrefab.InstantiateInactive();
tornadoGO.transform.parent = sector.transform;
tornadoGO.transform.position = planetGO.transform.TransformPoint(position);
tornadoGO.transform.rotation = Quaternion.FromToRotation(Vector3.up, sector.transform.TransformDirection(position.normalized));
// Add the sound thing before changing the scale
var soundGO = soundPrefab.InstantiateInactive();
var soundGO = _soundPrefab.InstantiateInactive();
soundGO.name = "AudioRail";
soundGO.transform.parent = tornadoGO.transform;
soundGO.transform.localPosition = Vector3.zero;
@ -79,7 +113,6 @@ namespace NewHorizons.Builder.Props
audioSource.playOnAwake = true;
var scale = info.height == 0 ? 1 : info.height / 10f;
tornadoGO.transform.localScale = Vector3.one * scale;
// Resize the distance it can be heard from to match roughly with the size
@ -102,28 +135,124 @@ namespace NewHorizons.Builder.Props
tornadoGO.GetComponentInChildren<CapsuleShape>().enabled = true;
// Resize it so the force volume goes all the way up
switch (downwards)
{
case true:
tornadoGO.transform.Find("MockDownTornado_FluidCenter").localScale = new Vector3(1, 2f, 1);
break;
default:
tornadoGO.transform.Find("MockUpTornado_FluidCenter").localScale = new Vector3(1, 2f, 1);
break;
}
if (info.tint != null)
{
var colour = info.tint.ToColor();
foreach (var renderer in tornadoGO.GetComponentsInChildren<Renderer>())
{
renderer.material.color = colour;
renderer.material.SetColor("_DetailColor", colour);
renderer.material.SetColor("_TintColor", colour);
}
ApplyTint(tornadoGO, info.tint.ToColor(), false, downwards);
}
if (info.wanderRate != 0)
{
var wanderer = tornadoGO.AddComponent<NHTornadoWanderController>();
wanderer.wanderRate = info.wanderRate;
wanderer.wanderDegreesX = info.wanderDegreesX;
wanderer.wanderDegreesZ = info.wanderDegreesZ;
wanderer.sector = sector;
ApplyWanderer(tornadoGO, sector, info);
}
soundGO.SetActive(true);
tornadoGO.SetActive(true);
}
private static void MakeHurricane(GameObject planetGO, Sector sector, PropModule.TornadoInfo info, Vector3 position, bool hasClouds)
{
var hurricaneGO = _hurricanePrefab.InstantiateInactive();
hurricaneGO.transform.parent = sector.transform;
hurricaneGO.transform.position = planetGO.transform.TransformPoint(position);
hurricaneGO.transform.rotation = Quaternion.FromToRotation(Vector3.up, sector.transform.TransformDirection(position.normalized));
var fluidVolume = hurricaneGO.GetComponentInChildren<HurricaneFluidVolume>();
fluidVolume._density = 8;
var effects = hurricaneGO.transform.Find("Effects_GD_Hurricane").gameObject;
if (!hasClouds)
{
foreach (Transform child in effects.transform)
{
if (child.name.Contains("HurricaneCloudBlend"))
{
child.localPosition = new Vector3(0, 60, 0);
child.localScale = Vector3.one * 1.1f;
}
if (child.name.Equals("Effects_GD_HurricaneCycloneExterior"))
{
child.localScale = new Vector3(0.88f, 1f, 0.88f);
}
}
}
// Rotation is off by default for some reason
foreach (var rotate in hurricaneGO.GetComponentsInChildren<RotateTransform>())
{
rotate._sector = sector;
}
// Streaming render mesh handles scare me
foreach(var streamingRenderMeshHandle in hurricaneGO.GetComponentsInChildren<StreamingRenderMeshHandle>())
{
streamingRenderMeshHandle.enabled = false;
}
// Height of the hurricane is 405 by default
if (info.height != 0) hurricaneGO.transform.localScale = Vector3.one * info.height / 405f;
if (info.tint != null)
{
ApplyTint(hurricaneGO, info.tint.ToColor(), true, false);
}
if (info.wanderRate != 0)
{
ApplyWanderer(hurricaneGO, sector, info);
}
hurricaneGO.SetActive(true);
}
private static void ApplyTint(GameObject go, Color colour, bool hurricane, bool downwards)
{
colour.a = 1f;
var detailTexture = ImageUtilities.TintImage(_detailTexture, colour);
var mainTexture = ImageUtilities.TintImage(_mainTexture, colour);
string materialName;
if (hurricane) materialName = "Hurricane_GD_Cyclone_mat";
else materialName = $"Tornado_BH_Cyclone_{(downwards ? "Down" : "Up")}_mat";
foreach (var renderer in go.GetComponentsInChildren<Renderer>())
{
renderer.material.SetColor(DetailColor, colour);
renderer.material.SetColor(TintColor, colour);
if (renderer.material.name.Contains(materialName))
{
renderer.material.SetTexture(DetailTex, detailTexture);
renderer.material.SetTexture(MainTex, mainTexture);
renderer.material.SetColor(FresnelColor, colour);
}
else
{
// If we set the colour on the ones with the material from before, it makes the gradient look bad
renderer.material.color = colour;
}
}
}
private static void ApplyWanderer(GameObject go, Sector sector, PropModule.TornadoInfo info)
{
var wanderer = go.AddComponent<NHTornadoWanderController>();
wanderer.wanderRate = info.wanderRate;
wanderer.wanderDegreesX = info.wanderDegreesX;
wanderer.wanderDegreesZ = info.wanderDegreesZ;
wanderer.sector = sector;
}
}
}

View File

@ -7,6 +7,8 @@ namespace NewHorizons.Builder.Props
{
private static Color defaultStoneTint = new Color(0.07450981f, 0.07450981f, 0.07450981f);
private static Color defaultLavaTint = new Color(4.594794f, 0.3419145f, 0f, 1f);
private static readonly int Color1 = Shader.PropertyToID("_Color");
private static readonly int EmissionColor = Shader.PropertyToID("_EmissionColor");
public static void Make(GameObject planetGO, Sector sector, PropModule.VolcanoInfo info)
{
@ -48,8 +50,8 @@ namespace NewHorizons.Builder.Props
meteor.transform.localScale = Vector3.one * info.scale;
var mat = meteor.GetComponentInChildren<MeshRenderer>().material;
mat.SetColor("_Color", info.stoneTint == null ? defaultStoneTint : info.stoneTint.ToColor());
mat.SetColor("_EmissionColor", info.lavaTint == null ? defaultLavaTint : info.lavaTint.ToColor());
mat.SetColor(Color1, info.stoneTint?.ToColor() ?? defaultStoneTint);
mat.SetColor(EmissionColor, info.lavaTint?.ToColor() ?? defaultLavaTint);
var detectors = meteor.transform.Find("ConstantDetectors").gameObject;
GameObject.Destroy(detectors.GetComponent<ConstantForceDetector>());

View File

@ -12,7 +12,7 @@ namespace NewHorizons.Components
// Temporary solution that i will never get rid of
transform.position = anchor.position;
float num = scaleCurve == null ? 1f : scaleCurve.Evaluate(TimeLoop.GetMinutesElapsed());
float num = scaleCurve?.Evaluate(TimeLoop.GetMinutesElapsed()) ?? 1f;
var dist = (transform.position - target.position).magnitude;
transform.localScale = new Vector3(num, num, dist / 500f);

View File

@ -7,14 +7,19 @@ namespace NewHorizons.Components
{
public void Awake()
{
var config = new PlanetConfig();
config.Base.SurfaceSize = 10f;
var config = new PlanetConfig
{
Base =
{
SurfaceSize = 10f
}
};
var detector = base.transform.GetComponentInChildren<DynamicForceDetector>();
var ao = base.GetComponent<AstroObject>();
var newDetector = DetectorBuilder.Make(base.gameObject, ao.GetAttachedOWRigidbody(), ao.GetPrimaryBody(), ao, config);
var detector = transform.GetComponentInChildren<DynamicForceDetector>();
var ao = GetComponent<AstroObject>();
var newDetector = DetectorBuilder.Make(gameObject, ao.GetAttachedOWRigidbody(), ao.GetPrimaryBody(), ao, config);
newDetector.transform.parent = detector.transform.parent;
GameObject.Destroy(detector);
Destroy(detector);
}
}
}

View File

@ -19,24 +19,37 @@ namespace NewHorizons.Components.Orbital
void Update()
{
if (Primary == null || Secondary == null) return;
// Secondary and primary must have been engulfed by a star
if (!Primary.isActiveAndEnabled && !Secondary.isActiveAndEnabled)
if (Primary == null || Secondary == null)
{
ReferenceFrameTracker component = Locator.GetPlayerBody().GetComponent<ReferenceFrameTracker>();
if (component.GetReferenceFrame(true) != null && component.GetReferenceFrame(true).GetOWRigidBody() == gameObject)
{
component.UntargetReferenceFrame();
}
MapMarker component2 = gameObject.GetComponent<MapMarker>();
if (component2 != null)
{
component2.DisableMarker();
}
CleanUp();
gameObject.SetActive(false);
FakeMassBody.SetActive(false);
}
else
{
// Secondary and primary must have been engulfed by a star
if (!Primary.isActiveAndEnabled && !Secondary.isActiveAndEnabled)
{
CleanUp();
gameObject.SetActive(false);
}
}
}
private void CleanUp()
{
ReferenceFrameTracker component = Locator.GetPlayerBody()?.GetComponent<ReferenceFrameTracker>();
if (component?.GetReferenceFrame(true)?.GetOWRigidBody() == gameObject)
{
component.UntargetReferenceFrame();
}
MapMarker component2 = gameObject.GetComponent<MapMarker>();
if (component2 != null)
{
component2.DisableMarker();
}
FakeMassBody.SetActive(false);
}
}
}

View File

@ -1,61 +0,0 @@
namespace NewHorizons.Components
{
public class TornadoFix : SectoredMonoBehaviour
{
public TornadoController tornadoController;
public new void Awake()
{
base.Awake();
tornadoController = GetComponent<TornadoController>();
tornadoController._tornadoRoot.SetActive(false);
tornadoController._formationDuration = 1f;
tornadoController._collapseDuration = 1f;
if (_sector != null)
{
_sector.OnOccupantEnterSector += OnOccupantEnterSector;
_sector.OnOccupantExitSector += OnOccupantExitSector;
}
}
public new void SetSector(Sector sector)
{
if (_sector != null)
{
_sector.OnOccupantEnterSector -= OnOccupantEnterSector;
_sector.OnOccupantExitSector -= OnOccupantExitSector;
}
base.SetSector(sector);
_sector.OnOccupantEnterSector += OnOccupantEnterSector;
_sector.OnOccupantExitSector += OnOccupantExitSector;
}
public new void OnDestroy()
{
base.OnDestroy();
_sector.OnOccupantEnterSector -= OnOccupantEnterSector;
_sector.OnOccupantExitSector -= OnOccupantExitSector;
}
public void OnOccupantEnterSector(SectorDetector _)
{
// Only form if not active and not forming
if (tornadoController._tornadoRoot.activeInHierarchy || tornadoController._tornadoForming) return;
tornadoController.StartFormation();
}
public void OnOccupantExitSector(SectorDetector _)
{
if (_sector.ContainsAnyOccupants(DynamicOccupant.Player | DynamicOccupant.Probe | DynamicOccupant.Ship)) return;
// If the root is inactive it has collapsed. Also don't collapse if we're already doing it
if (!tornadoController._tornadoRoot.activeInHierarchy || tornadoController._tornadoCollapsing) return;
tornadoController.StartCollapse();
}
}
}

View File

@ -1,6 +1,10 @@
using NewHorizons.External.Modules;
using NewHorizons.External.Modules.VariableSize;
using Newtonsoft.Json;
using NewHorizons.Utility;
using System.ComponentModel;
using UnityEngine;
using UnityEngine.Internal;
namespace NewHorizons.External.Configs
{
@ -23,6 +27,7 @@ namespace NewHorizons.External.Configs
/// <summary>
/// Unique star system containing your planet
/// </summary>
[DefaultValue("SolarSystem")]
public string StarSystem = "SolarSystem";
/// <summary>
@ -38,6 +43,7 @@ namespace NewHorizons.External.Configs
/// <summary>
/// Set to a higher number if you wish for this body to be built sooner
/// </summary>
[DefaultValue(-1)]
public int BuildPriority = -1;
/// <summary>
@ -235,6 +241,14 @@ namespace NewHorizons.External.Configs
Atmosphere.UseAtmosphereShader = true;
}
}
if(Props?.Tornados != null)
{
foreach(var tornado in Props.Tornados)
{
if (tornado.downwards) tornado.type = "downwards";
}
}
#pragma warning restore 612, 618
}
}

View File

@ -1,4 +1,5 @@
using Newtonsoft.Json;
using System.ComponentModel;
namespace NewHorizons.External.Configs
{
@ -8,6 +9,11 @@ namespace NewHorizons.External.Configs
[JsonObject]
public class StarSystemConfig
{
/// <summary>
/// Relative path to the image file to use as the subtitle image (replaces the eote banner)
/// </summary>
public string subtitle;
/// <summary>
/// Whether this system can be warped to via the warp drive
/// </summary>
@ -27,15 +33,6 @@ namespace NewHorizons.External.Configs
/// Set to the FactID that must be revealed before it can be warped to. Don't set `CanEnterViaWarpDrive` to `false` if you're using this, that would make no sense.
/// </summary>
public string factRequiredForWarp;
/// <summary>
/// Should the player be sent back in time after 22 minutes?
/// </summary>
public bool enableTimeLoop = true;
/// <summary>
/// Should the player be unable to use their map in this system?
/// </summary>
public bool mapRestricted;
/// <summary>

View File

@ -1,4 +1,6 @@
using Newtonsoft.Json;
using UnityEngine.Internal;
using System.ComponentModel;
namespace NewHorizons.External.Modules
{
@ -18,16 +20,19 @@ namespace NewHorizons.External.Modules
/// <summary>
/// Minimum size of the asteroids.
/// </summary>
public float MinSize = 20f;
[DefaultValue(20)]
public float MinSize = 20;
/// <summary>
/// Maximum size of the asteroids.
/// </summary>
[DefaultValue(50)]
public float MaxSize = 50f;
/// <summary>
/// Amount of asteroids to create.
/// </summary>
[DefaultValue(-1)]
public int Amount = -1;
/// <summary>

View File

@ -1,5 +1,6 @@
using System.Runtime.Serialization;
using NewHorizons.Utility;
using System.ComponentModel;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
@ -87,7 +88,7 @@ namespace NewHorizons.External.Modules
[JsonConverter(typeof(StringEnumConverter))]
public CloudFluidType? FluidType;
[System.Obsolete("UseBasicCloudShader is deprecated, please use CloudInfo instead")] public bool UseBasicCloudShader;
[System.Obsolete("ShadowsOnClouds is deprecated, please use CloudInfo instead")] public bool ShadowsOnClouds = true;
[DefaultValue(true)] [System.Obsolete("ShadowsOnClouds is deprecated, please use CloudInfo instead")] public bool ShadowsOnClouds = true;
[System.Obsolete("HasAtmosphere is deprecated, please use UseAtmosphereShader instead")] public bool HasAtmosphere;
#endregion Obsolete

View File

@ -1,6 +1,8 @@
using System.Runtime.Serialization;
using NewHorizons.Utility;
using Newtonsoft.Json;
using System.ComponentModel;
using UnityEngine.Internal;
namespace NewHorizons.External.Modules
{
@ -65,6 +67,7 @@ namespace NewHorizons.External.Modules
/// <summary>
/// Allows the object to be targeted on the map.
/// </summary>
[DefaultValue(true)]
public bool HasReferenceFrame = true;
/// <summary>
@ -85,6 +88,7 @@ namespace NewHorizons.External.Modules
/// <summary>
/// Do we show the minimap when walking around this planet?
/// </summary>
[DefaultValue(true)]
public bool ShowMinimap = true;
#region Obsolete

View File

@ -2,6 +2,8 @@
using NewHorizons.Utility;
using Newtonsoft.Json;
using UnityEngine;
using System.ComponentModel;
using UnityEngine.Internal;
namespace NewHorizons.External.Modules
{
@ -71,6 +73,7 @@ namespace NewHorizons.External.Modules
/// <summary>
/// Referring to the orbit line in the map screen.
/// </summary>
[DefaultValue(true)]
public bool ShowOrbitLine { get; set; } = true;
/// <summary>
@ -91,7 +94,7 @@ namespace NewHorizons.External.Modules
/// <summary>
/// Should we just draw a line behind its orbit instead of the entire circle/ellipse?
/// </summary>
public bool TrackingOrbitLine { get; set; } = false;
public bool TrackingOrbitLine { get; set; }
public OrbitalParameters GetOrbitalParameters(Gravity primaryGravity, Gravity secondaryGravity)
{

View File

@ -1,5 +1,6 @@
using System.Runtime.Serialization;
using NewHorizons.Utility;
using System.ComponentModel;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
@ -143,6 +144,7 @@ namespace NewHorizons.External.Modules
/// <summary>
/// Scale the prop
/// </summary>
[DefaultValue(1f)]
public float scale = 1f;
/// <summary>
@ -195,6 +197,7 @@ namespace NewHorizons.External.Modules
/// <summary>
/// The height of this tornado.
/// </summary>
[DefaultValue(30f)]
public float height = 30f;
/// <summary>
@ -211,15 +214,17 @@ namespace NewHorizons.External.Modules
/// The rate at which the tornado will wander around the planet. Set to 0 for it to be stationary. Should be around 0.1.
/// </summary>
public float wanderRate;
/// <summary>
/// Angular distance from the starting position that it will wander, in terms of the angle around the x-axis.
/// </summary>
[DefaultValue(45f)]
public float wanderDegreesX = 45f;
/// <summary>
/// Angular distance from the starting position that it will wander, in terms of the angle around the z-axis.
/// </summary>
[DefaultValue(45f)]
public float wanderDegreesZ = 45f;
}

View File

@ -1,5 +1,6 @@
using NewHorizons.Utility;
using Newtonsoft.Json;
using System.ComponentModel;
namespace NewHorizons.External.Modules
{
@ -52,6 +53,7 @@ namespace NewHorizons.External.Modules
/// <summary>
/// Scale to apply to the planet in map mode.
/// </summary>
[DefaultValue(1f)]
public float scale = 1f;
/// <summary>

View File

@ -1,5 +1,6 @@
using NewHorizons.Utility;
using Newtonsoft.Json;
using System.ComponentModel;
namespace NewHorizons.External.Modules
{
@ -42,11 +43,13 @@ namespace NewHorizons.External.Modules
/// <summary>
/// A ship log fact to reveal when the signal is identified.
/// </summary>
[DefaultValue("")]
public string Reveals = "";
/// <summary>
/// Radius of the sphere giving off the signal.
/// </summary>
[DefaultValue(1f)]
public float SourceRadius = 1f;
/// <summary>
@ -57,11 +60,13 @@ namespace NewHorizons.External.Modules
/// <summary>
/// How close the player must get to the signal to identify it. This is when you learn its name.
/// </summary>
[DefaultValue(10f)]
public float IdentificationRadius = 10f;
/// <summary>
/// `false` if the player can hear the signal without equipping the signal-scope.
/// </summary>
[DefaultValue(true)]
public bool OnlyAudibleToScope = true;
/// <summary>

View File

@ -2,6 +2,7 @@
using NewHorizons.Utility;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.ComponentModel;
namespace NewHorizons.External.Modules.VariableSize
{
@ -46,6 +47,7 @@ namespace NewHorizons.External.Modules.VariableSize
/// <summary>
/// Only for White Holes. Should this white hole repel the player from it.
/// </summary>
[DefaultValue(true)]
public bool MakeZeroGVolume = true;
}
}

View File

@ -1,5 +1,7 @@
using NewHorizons.Utility;
using Newtonsoft.Json;
using System.ComponentModel;
using UnityEngine.Internal;
namespace NewHorizons.External.Modules.VariableSize
{
@ -9,6 +11,7 @@ namespace NewHorizons.External.Modules.VariableSize
/// <summary>
/// Radius of the star.
/// </summary>
[DefaultValue(2000f)]
public float Size = 2000f;
/// <summary>
@ -34,16 +37,19 @@ namespace NewHorizons.External.Modules.VariableSize
/// <summary>
/// Relative strength of the light compared to the sun.
/// </summary>
[DefaultValue(1f)]
public float SolarLuminosity = 1f;
/// <summary>
/// The default sun has its own atmosphere that is different from regular planets. If you want that, set this to `true`.
/// </summary>
[DefaultValue(true)]
public bool HasAtmosphere = true;
/// <summary>
/// Should this star explode after 22 minutes?
/// </summary>
[DefaultValue(true)]
public bool GoSupernova = true;
}
}

View File

@ -0,0 +1,118 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using NewHorizons.Utility;
using OWML.Common;
namespace NewHorizons.Handlers
{
class SubtitlesHandler : MonoBehaviour
{
public static int SUBTITLE_HEIGHT = 97;
public static int SUBTITLE_WIDTH = 669; // nice
Graphic graphic;
Image image;
public float fadeSpeed = 0.005f;
float fade = 1;
bool fadingAway = true;
static List<Sprite> possibleSubtitles = new List<Sprite>();
static bool eoteSubtitleHasBeenInserted = false;
int subtitleIndex;
System.Random randomizer;
static readonly int PAUSE_TIMER_MAX = 50;
int pauseTimer = PAUSE_TIMER_MAX;
public void Start()
{
randomizer = new System.Random();
GetComponent<CanvasGroup>().alpha = 1;
graphic = GetComponent<Graphic>();
image = GetComponent<UnityEngine.UI.Image>();
graphic.enabled = true;
image.enabled = true;
if (!Main.HasDLC) image.sprite = null; // Just in case. I don't know how not having the dlc changes the subtitle game object
if (!eoteSubtitleHasBeenInserted)
{
if (image.sprite != null) possibleSubtitles.Insert(0, image.sprite); // ensure that the Echoes of the Eye subtitle always appears first
eoteSubtitleHasBeenInserted = true;
}
}
public static void AddSubtitle(IModBehaviour mod, string filepath)
{
var tex = ImageUtilities.GetTexture(mod, filepath);
if (tex == null) return;
// var sprite = Sprite.Create(tex, new Rect(0.0f, 0.0f, tex.width, tex.height), new Vector2(0.5f, 0.5f), 100.0f);
var sprite = Sprite.Create(tex, new Rect(0.0f, 0.0f, tex.width, SUBTITLE_HEIGHT), new Vector2(0.5f, 0.5f), 100.0f);
AddSubtitle(sprite);
}
public static void AddSubtitle(Sprite sprite)
{
possibleSubtitles.Add(sprite);
}
public void Update()
{
if (image.sprite == null) image.sprite = possibleSubtitles[0];
// don't fade transition subtitles if there's only one subtitle
if (possibleSubtitles.Count <= 1) return;
if (pauseTimer > 0)
{
pauseTimer--;
return;
}
if (fadingAway)
{
fade -= fadeSpeed;
if (fade <= 0)
{
fade = 0;
ChangeSubtitle();
fadingAway = false;
}
}
else
{
fade += fadeSpeed;
if (fade >= 1)
{
fade = 1;
fadingAway = true;
pauseTimer = PAUSE_TIMER_MAX;
}
}
graphic.color = new Color(1, 1, 1, fade);
}
public void ChangeSubtitle()
{
// to pick a new random subtitle without requiring retries, we generate a random offset less than the length of the possible subtitles array
// we then add that offset to the current index, modulo NUMBER_OF_POSSIBLE_SUBTITLES
// since the offset can never be NUMBER_OF_POSSIBLE_SUBTITLES, it will never wrap all the way back around to the initial subtitleIndex
// note, this makes the code more confusing, but Random.Next(min, max) generates a random number on the range [min, max)
// that is, the below code will generate numbers up to and including Count-1, not Count.
var newIndexOffset = randomizer.Next(1, possibleSubtitles.Count);
subtitleIndex = (subtitleIndex + newIndexOffset) % possibleSubtitles.Count;
image.sprite = possibleSubtitles[subtitleIndex];
}
}
}

View File

@ -11,6 +11,20 @@ namespace NewHorizons.Handlers
{
public static class TitleSceneHandler
{
public static void InitSubtitles()
{
GameObject subtitleContainer = GameObject.Find("TitleMenu/TitleCanvas/TitleLayoutGroup/Logo_EchoesOfTheEye");
if (subtitleContainer == null)
{
Logger.LogError("No subtitle container found! Failed to load subtitles.");
return;
}
subtitleContainer.SetActive(true);
subtitleContainer.AddComponent<SubtitlesHandler>();
}
public static void DisplayBodyOnTitleScreen(List<NewHorizonsBody> bodies)
{
//Try loading one planet why not

View File

@ -18,6 +18,7 @@ using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using Logger = NewHorizons.Utility.Logger;
using NewHorizons.Utility.DebugUtilities;
namespace NewHorizons
{
@ -85,6 +86,7 @@ namespace NewHorizons
Debug = config.GetSettingsValue<bool>("Debug");
DebugReload.UpdateReloadButton();
DebugMenu.UpdatePauseMenuButton();
Logger.UpdateLogLevel(Debug ? Logger.LogType.Log : Logger.LogType.Error);
_defaultSystemOverride = config.GetSettingsValue<string>("Default System Override");
@ -231,6 +233,7 @@ namespace NewHorizons
if (scene.name == "TitleScreen" && _useCustomTitleScreen)
{
TitleSceneHandler.DisplayBodyOnTitleScreen(BodyDict.Values.ToList().SelectMany(x => x).ToList());
TitleSceneHandler.InitSubtitles();
}
if (scene.name == "EyeOfTheUniverse" && IsWarping)
@ -301,6 +304,8 @@ namespace NewHorizons
private void OnSystemReady(bool shouldWarpIn)
{
Locator.GetPlayerBody().gameObject.AddComponent<DebugRaycaster>();
Locator.GetPlayerBody().gameObject.AddComponent<DebugPropPlacer>();
Locator.GetPlayerBody().gameObject.AddComponent<DebugMenu>();
if (shouldWarpIn) _shipWarpController.WarpIn(WearingSuit);
else FindObjectOfType<PlayerSpawner>().DebugWarp(SystemDict[_currentStarSystem].SpawnPoint);
@ -343,6 +348,11 @@ namespace NewHorizons
if (name != "SolarSystem") SetDefaultSystem(name);
}
if (starSystemConfig.subtitle != null)
{
SubtitlesHandler.AddSubtitle(mod, starSystemConfig.subtitle);
}
var system = new NewHorizonsSystem(name, starSystemConfig, mod);
SystemDict[name] = system;
}
@ -428,7 +438,7 @@ namespace NewHorizons
BodyDict.Add(config.StarSystem, new List<NewHorizonsBody>());
}
body = new NewHorizonsBody(config, mod);
body = new NewHorizonsBody(config, mod, relativeDirectory);
}
catch (Exception e)
{

View File

@ -1086,9 +1086,14 @@
"$ref": "#/$defs/color",
"description": "The colour of the tornado."
},
"downwards": {
"type": "boolean",
"description": "Should it pull things downwards? Will push them upwards by default."
"type": {
"type": "string",
"enum": [
"downwards",
"upwards",
"hurricane"
],
"description": "What type of cyclone should this be? Upwards and downwards are both tornados and will push in that direction."
},
"wanderRate": {
"type": "number",
@ -1097,12 +1102,12 @@
},
"wanderDegreesX": {
"type": "number",
"description": "Angular distance from the starting position that it will wander, in terms of the angle around the x-axis.",
"description": "Angular distance from the starting position that it will wander, in terms of the azimuthal angle (angle of rotation around the polar axis).",
"default": 45
},
"wanderDegreesZ": {
"type": "number",
"description": "Angular distance from the starting position that it will wander, in terms of the angle around the z-axis.",
"description": "Angular distance from the starting position that it will wander, in terms of the polar angle (angle between the radial vector and the polar axis).",
"default": 45
}
}

View File

@ -30,6 +30,10 @@
"description": "Should the player be unable to use their map in this system?",
"default": false
},
"subtitle": {
"type": "string",
"description": "Relative path to a subtitle image to be displayed on the main menu scene. The image should be 669x97 resolution."
},
"skybox": {
"type": "object",
"description": "Options for the skybox of your system",

View File

@ -1,54 +0,0 @@
using UnityEngine;
using UnityEngine.InputSystem;
namespace NewHorizons.Utility
{
[RequireComponent(typeof(OWRigidbody))]
public class DebugRaycaster : MonoBehaviour
{
private OWRigidbody _rb;
private GameObject _surfaceSphere;
private GameObject _normalSphere1;
private GameObject _normalSphere2;
private void Awake()
{
_rb = this.GetRequiredComponent<OWRigidbody>();
}
private void Update()
{
if (Main.Debug && Keyboard.current != null && Keyboard.current[Key.P].wasReleasedThisFrame)
{
// Raycast
_rb.DisableCollisionDetection();
int layerMask = OWLayerMask.physicalMask;
var origin = Locator.GetActiveCamera().transform.position;
var direction = Locator.GetActiveCamera().transform.TransformDirection(Vector3.forward);
if (Physics.Raycast(origin, direction, out RaycastHit hitInfo, 100f, layerMask))
{
var pos = hitInfo.transform.InverseTransformPoint(hitInfo.point);
var norm = hitInfo.transform.InverseTransformDirection(hitInfo.normal);
var o = hitInfo.transform.gameObject;
var posText = $"{{\"x\": {pos.x}, \"y\": {pos.y}, \"z\": {pos.z}}}";
var normText = $"{{\"x\": {norm.x}, \"y\": {norm.y}, \"z\": {norm.z}}}";
if (_surfaceSphere != null) GameObject.Destroy(_surfaceSphere);
if (_normalSphere1 != null) GameObject.Destroy(_normalSphere1);
if (_normalSphere2 != null) GameObject.Destroy(_normalSphere2);
_surfaceSphere = AddDebugShape.AddSphere(hitInfo.transform.gameObject, 0.1f, Color.green);
_normalSphere1 = AddDebugShape.AddSphere(hitInfo.transform.gameObject, 0.01f, Color.red);
_normalSphere2 = AddDebugShape.AddSphere(hitInfo.transform.gameObject, 0.01f, Color.red);
_surfaceSphere.transform.localPosition = pos;
_normalSphere1.transform.localPosition = pos + norm * 0.5f;
_normalSphere2.transform.localPosition = pos + norm;
Logger.Log($"Raycast hit \"position\": {posText}, \"normal\": {normText} on [{o.name}] at [{SearchUtilities.GetPath(o.transform)}]");
}
_rb.EnableCollisionDetection();
}
}
}
}

View File

@ -0,0 +1,353 @@
using NewHorizons.External;
using NewHorizons.External.Configs;
using NewHorizons.External.Modules;
using NewHorizons.Handlers;
using Newtonsoft.Json;
using OWML.Common;
using OWML.Common.Menus;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.InputSystem;
namespace NewHorizons.Utility.DebugUtilities
{
//
//
// TODO: split this into two separate classes "DebugMenu" and "DebugPropPlacerMenu"
//
//
[RequireComponent(typeof(DebugRaycaster))]
[RequireComponent(typeof(DebugPropPlacer))]
class DebugMenu : MonoBehaviour
{
private static IModButton pauseMenuButton;
GUIStyle _editorMenuStyle;
Vector2 EditorMenuSize = new Vector2(600, 900);
bool menuOpen = false;
static bool openMenuOnPause;
static bool staticInitialized;
DebugPropPlacer _dpp;
DebugRaycaster _drc;
// menu params
private Vector2 recentPropsScrollPosition = Vector2.zero;
private HashSet<string> favoriteProps = new HashSet<string>();
public static readonly char separatorCharacter = '☧'; // since no chars are illegal in game object names, I picked one that's extremely unlikely to be used to be a separator
private static readonly string favoritePropsPlayerPrefKey = "FavoriteProps";
private static IModBehaviour loadedMod = null;
private Dictionary<string, PlanetConfig> loadedConfigFiles = new Dictionary<string, PlanetConfig>();
private bool saveButtonUnlocked = false;
private Vector2 recentModListScrollPosition = Vector2.zero;
private static JsonSerializerSettings jsonSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore,
Formatting = Formatting.Indented,
};
private void Awake()
{
_dpp = this.GetRequiredComponent<DebugPropPlacer>();
_drc = this.GetRequiredComponent<DebugRaycaster>();
LoadFavoriteProps();
}
private void Start()
{
if (!staticInitialized)
{
staticInitialized = true;
Main.Instance.ModHelper.Menus.PauseMenu.OnInit += PauseMenuInitHook;
Main.Instance.ModHelper.Menus.PauseMenu.OnClosed += CloseMenu;
Main.Instance.ModHelper.Menus.PauseMenu.OnOpened += RestoreMenuOpennessState;
PauseMenuInitHook();
Main.Instance.OnChangeStarSystem.AddListener((string s) => SaveLoadedConfigsForRecentSystem());
}
else
{
InitMenu();
}
if (loadedMod != null)
{
LoadMod(loadedMod);
}
}
private void PauseMenuInitHook()
{
pauseMenuButton = Main.Instance.ModHelper.Menus.PauseMenu.OptionsButton.Duplicate(TranslationHandler.GetTranslation("Toggle Prop Placer Menu", TranslationHandler.TextType.UI).ToUpper());
InitMenu();
}
public static void UpdatePauseMenuButton()
{
if (pauseMenuButton != null)
{
if (Main.Debug) pauseMenuButton.Show();
else pauseMenuButton.Hide();
}
}
private void RestoreMenuOpennessState() { menuOpen = openMenuOnPause; }
private void ToggleMenu() { menuOpen = !menuOpen; openMenuOnPause = !openMenuOnPause; }
private void CloseMenu() { menuOpen = false; }
private void LoadFavoriteProps()
{
string favoritePropsPlayerPref = PlayerPrefs.GetString(favoritePropsPlayerPrefKey);
if (favoritePropsPlayerPref == null || favoritePropsPlayerPref == "") return;
var favoritePropPaths = favoritePropsPlayerPref.Split(separatorCharacter);
foreach (string favoriteProp in favoritePropPaths)
{
DebugPropPlacer.RecentlyPlacedProps.Add(favoriteProp);
this.favoriteProps.Add(favoriteProp);
}
}
private void OnGUI()
{
if (!menuOpen) return;
if (!Main.Debug) return;
Vector2 menuPosition = new Vector2(10, 40);
GUILayout.BeginArea(new Rect(menuPosition.x, menuPosition.y, EditorMenuSize.x, EditorMenuSize.y), _editorMenuStyle);
//
// DebugPropPlacer
//
GUILayout.Label("Recently placed objects");
_dpp.SetCurrentObject(GUILayout.TextArea(_dpp.currentObject));
GUILayout.Space(5);
// List of recently placed objects
GUILayout.Label("Recently placed objects");
recentPropsScrollPosition = GUILayout.BeginScrollView(recentPropsScrollPosition, GUILayout.Width(EditorMenuSize.x), GUILayout.Height(100));
foreach (string propPath in DebugPropPlacer.RecentlyPlacedProps)
{
GUILayout.BeginHorizontal();
var propPathElements = propPath[propPath.Length-1] == '/'
? propPath.Substring(0, propPath.Length-1).Split('/')
: propPath.Split('/');
string propName = propPathElements[propPathElements.Length - 1];
string favoriteButtonIcon = favoriteProps.Contains(propPath) ? "★" : "☆";
if (GUILayout.Button(favoriteButtonIcon, GUILayout.ExpandWidth(false)))
{
if (favoriteProps.Contains(propPath))
{
favoriteProps.Remove(propPath);
}
else
{
favoriteProps.Add(propPath);
}
string[] favoritePropsArray = favoriteProps.ToArray<string>();
PlayerPrefs.SetString(favoritePropsPlayerPrefKey, string.Join(separatorCharacter + "", favoritePropsArray));
}
if (GUILayout.Button(propName))
{
_dpp.SetCurrentObject(propPath);
}
GUILayout.EndHorizontal();
}
GUILayout.EndScrollView();
GUILayout.Space(5);
// continue working on existing mod
GUILayout.Label("Name of your mod");
if (loadedMod == null)
{
recentModListScrollPosition = GUILayout.BeginScrollView(recentModListScrollPosition, GUILayout.Width(EditorMenuSize.x), GUILayout.Height(100));
foreach (var mod in Main.MountedAddons)
{
if (GUILayout.Button(mod.ModHelper.Manifest.UniqueName))
{
LoadMod(mod);
}
}
GUILayout.EndScrollView();
}
else
{
GUILayout.Label(loadedMod.ModHelper.Manifest.UniqueName);
}
GUILayout.Space(5);
// save your work
{
GUILayout.BeginHorizontal();
if (GUILayout.Button(saveButtonUnlocked ? " O " : " | ", GUILayout.ExpandWidth(false)))
{
saveButtonUnlocked = !saveButtonUnlocked;
}
GUI.enabled = saveButtonUnlocked;
if (GUILayout.Button("Update your mod's configs"))
{
SaveLoadedConfigsForRecentSystem();
saveButtonUnlocked = false;
}
GUI.enabled = true;
GUILayout.EndHorizontal();
}
GUILayout.EndArea();
}
private void LoadMod(IModBehaviour mod)
{
loadedMod = mod;
DebugPropPlacer.active = true;
var folder = loadedMod.ModHelper.Manifest.ModFolderPath;
List<NewHorizonsBody> bodiesForThisMod = Main.BodyDict.Values.SelectMany(x => x).Where(x => x.Mod == loadedMod).ToList();
foreach (NewHorizonsBody body in bodiesForThisMod)
{
if (body.RelativePath == null)
{
Logger.Log("Error loading config for " + body.Config.Name + " in " + body.Config.StarSystem);
}
loadedConfigFiles[folder + body.RelativePath] = (body.Config as PlanetConfig);
_dpp.FindAndRegisterPropsFromConfig(body.Config);
}
}
private void SaveLoadedConfigsForRecentSystem()
{
UpdateLoadedConfigsForRecentSystem();
string backupFolderName = "configBackups\\" + DateTime.Now.ToString("yyyyMMddTHHmmss") + "\\";
Logger.Log($"Potentially saving {loadedConfigFiles.Keys.Count} files");
foreach (var filePath in loadedConfigFiles.Keys)
{
Logger.Log("Possibly Saving... " + loadedConfigFiles[filePath].Name + " @ " + filePath);
if (loadedConfigFiles[filePath].StarSystem != Main.Instance.CurrentStarSystem) continue;
var relativePath = filePath.Replace(loadedMod.ModHelper.Manifest.ModFolderPath, "");
var json = JsonConvert.SerializeObject(loadedConfigFiles[filePath], jsonSettings);
// Add the schema line
json = "{\n\t\"$schema\": \"https://raw.githubusercontent.com/xen-42/outer-wilds-new-horizons/main/NewHorizons/Schemas/body_schema.json\"," + json.Substring(1);
try
{
Logger.Log("Saving... " + relativePath + " to " + filePath);
var path = loadedMod.ModHelper.Manifest.ModFolderPath + relativePath;
var directoryName = Path.GetDirectoryName(path);
Directory.CreateDirectory(directoryName);
File.WriteAllText(path, json);
}
catch (Exception e) { Logger.LogError("Failed to save file " + backupFolderName + relativePath); Logger.LogError(e.Message + "\n" + e.StackTrace); }
try
{
var path = Main.Instance.ModHelper.Manifest.ModFolderPath + backupFolderName + relativePath;
var directoryName = Path.GetDirectoryName(path);
Directory.CreateDirectory(directoryName);
File.WriteAllText(path, json);
}
catch (Exception e) { Logger.LogError("Failed to save backup file " + backupFolderName + relativePath); Logger.LogError(e.Message + "\n" + e.StackTrace); }
}
}
private void UpdateLoadedConfigsForRecentSystem()
{
var newDetails = _dpp.GetPropsConfigByBody();
Logger.Log("Updating config files. New Details Counts by planet: " + string.Join(", ", newDetails.Keys.Select(x => x + $" ({newDetails[x].Length})")));
Dictionary<string, string> planetToConfigPath = new Dictionary<string, string>();
// Get all configs
foreach (var filePath in loadedConfigFiles.Keys)
{
Logger.Log("potentially updating copy of config at " + filePath);
if (loadedConfigFiles[filePath].StarSystem != Main.Instance.CurrentStarSystem) return;
if (loadedConfigFiles[filePath].Name == null || AstroObjectLocator.GetAstroObject(loadedConfigFiles[filePath].Name) == null) { Logger.Log("Failed to update copy of config at " + filePath); continue; }
var astroObjectName = DebugPropPlacer.GetAstroObjectName(loadedConfigFiles[filePath].Name);
planetToConfigPath[astroObjectName] = filePath;
if (!newDetails.ContainsKey(astroObjectName)) continue;
if (loadedConfigFiles[filePath].Props == null) loadedConfigFiles[filePath].Props = new External.Modules.PropModule();
loadedConfigFiles[filePath].Props.Details = newDetails[astroObjectName];
Logger.Log("successfully updated copy of config file for " + astroObjectName);
}
// find all new planets that do not yet have config paths
var planetsThatDoNotHaveConfigFiles = newDetails.Keys.Where(x => !planetToConfigPath.ContainsKey(x)).ToList();
foreach (var astroObjectName in planetsThatDoNotHaveConfigFiles)
{
Logger.Log("Fabricating new config file for " + astroObjectName);
var filepath = "planets/" + Main.Instance.CurrentStarSystem + "/" + astroObjectName + ".json";
PlanetConfig c = new PlanetConfig();
c.StarSystem = Main.Instance.CurrentStarSystem;
c.Name = astroObjectName;
c.Props = new PropModule();
c.Props.Details = newDetails[astroObjectName];
loadedConfigFiles[filepath] = c;
}
}
private void InitMenu()
{
if (_editorMenuStyle != null) return;
UpdatePauseMenuButton();
// TODO: figure out how to clear this event list so that we don't pile up useless instances of the DebugMenu that can't get garbage collected
pauseMenuButton.OnClick += ToggleMenu;
_dpp = this.GetRequiredComponent<DebugPropPlacer>();
_drc = this.GetRequiredComponent<DebugRaycaster>();
Texture2D bgTexture = ImageUtilities.MakeSolidColorTexture((int)EditorMenuSize.x, (int)EditorMenuSize.y, Color.black);
_editorMenuStyle = new GUIStyle
{
normal =
{
background = bgTexture
}
};
}
}
}

View File

@ -0,0 +1,279 @@
using NewHorizons.Builder.Props;
using NewHorizons.External.Configs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.InputSystem;
using static NewHorizons.External.Modules.PropModule;
namespace NewHorizons.Utility.DebugUtilities
{
//
// The prop placer. Doesn't interact with any files, just places and tracks props.
//
[RequireComponent(typeof(DebugRaycaster))]
class DebugPropPlacer : MonoBehaviour
{
private struct PropPlacementData
{
public string body;
public string system;
public GameObject gameObject;
public DetailInfo detailInfo;
}
// VASE
public static readonly string DEFAULT_OBJECT = "BrittleHollow_Body/Sector_BH/Sector_NorthHemisphere/Sector_NorthPole/Sector_HangingCity/Sector_HangingCity_District1/Props_HangingCity_District1/OtherComponentsGroup/Props_HangingCity_Building_10/Prefab_NOM_VaseThin";
public string currentObject { get; private set; } // path of the prop to be placed
private bool hasAddedCurrentObjectToRecentsList = false;
private List<PropPlacementData> props = new List<PropPlacementData>();
private List<PropPlacementData> deletedProps = new List<PropPlacementData>();
private DebugRaycaster _rc;
public static HashSet<string> RecentlyPlacedProps = new HashSet<string>();
public static bool active = false;
private void Awake()
{
_rc = this.GetRequiredComponent<DebugRaycaster>();
currentObject = DEFAULT_OBJECT;
}
private void Update()
{
if (!Main.Debug) return;
if (!active) return;
if (Keyboard.current[Key.G].wasReleasedThisFrame)
{
PlaceObject();
}
if (Keyboard.current[Key.Minus].wasReleasedThisFrame)
{
DeleteLast();
}
if (Keyboard.current[Key.Equals].wasReleasedThisFrame)
{
UndoDelete();
}
}
public void SetCurrentObject(string s)
{
currentObject = s;
hasAddedCurrentObjectToRecentsList = false;
}
internal void PlaceObject()
{
DebugRaycastData data = _rc.Raycast();
PlaceObject(data, this.gameObject.transform.position);
if (!hasAddedCurrentObjectToRecentsList)
{
hasAddedCurrentObjectToRecentsList = true;
if (!RecentlyPlacedProps.Contains(currentObject))
{
RecentlyPlacedProps.Add(currentObject);
}
}
}
public void PlaceObject(DebugRaycastData data, Vector3 playerAbsolutePosition)
{
// TODO: implement sectors
// if this hits a sector, store that sector and add a config file option for it
if (!data.hitObject.name.EndsWith("_Body"))
{
Logger.Log("Cannot place object on non-body object: " + data.hitObject.name);
}
try
{
if (currentObject == "" || currentObject == null)
{
SetCurrentObject(DEFAULT_OBJECT);
}
GameObject prop = DetailBuilder.MakeDetail(data.hitObject, data.hitObject.GetComponentInChildren<Sector>(), currentObject, data.pos, data.norm, 1, false);
PropPlacementData propData = RegisterProp_WithReturn(data.bodyName, prop);
// align with surface normal
Vector3 alignToSurface = (Quaternion.LookRotation(data.norm) * Quaternion.FromToRotation(Vector3.up, Vector3.forward)).eulerAngles;
prop.transform.localEulerAngles = alignToSurface;
// rotate facing dir towards player
GameObject g = new GameObject();
g.transform.parent = prop.transform.parent;
g.transform.localPosition = prop.transform.localPosition;
g.transform.localRotation = prop.transform.localRotation;
prop.transform.parent = g.transform;
var dirTowardsPlayer = prop.transform.parent.transform.InverseTransformPoint(playerAbsolutePosition) - prop.transform.localPosition;
dirTowardsPlayer.y = 0;
float rotation = Quaternion.LookRotation(dirTowardsPlayer).eulerAngles.y;
prop.transform.localEulerAngles = new Vector3(0, rotation, 0);
prop.transform.parent = g.transform.parent;
GameObject.Destroy(g);
}
catch
{
Logger.Log($"Failed to place object {currentObject} on body ${data.hitObject} at location ${data.pos}.");
}
}
public static string GetAstroObjectName(string bodyName)
{
if (bodyName.EndsWith("_Body")) bodyName = bodyName.Substring(0, bodyName.Length-"_Body".Length);
var astroObject = AstroObjectLocator.GetAstroObject(bodyName);
if (astroObject == null) return null;
var astroObjectName = astroObject.name;
if (astroObjectName.EndsWith("_Body")) astroObjectName = astroObjectName.Substring(0, astroObjectName.Length-"_Body".Length);
return astroObjectName;
}
public void FindAndRegisterPropsFromConfig(PlanetConfig config)
{
if (config.StarSystem != Main.Instance.CurrentStarSystem) return;
AstroObject planet = AstroObjectLocator.GetAstroObject(config.Name);
if (planet == null) return;
if (config.Props == null || config.Props.Details == null) return;
var astroObjectName = GetAstroObjectName(config.Name);
foreach (var detail in config.Props.Details)
{
GameObject spawnedProp = DetailBuilder.GetSpawnedGameObjectByDetailInfo(detail);
if (spawnedProp == null)
{
Logger.LogError("No spawned prop found for " + detail.path);
continue;
}
PropPlacementData data = RegisterProp_WithReturn(astroObjectName, spawnedProp, detail.path, detail);
// note: we do not support placing props from assetbundles, so they will not be added to the
// selectable list of placed props
if (detail.assetBundle == null && !RecentlyPlacedProps.Contains(data.detailInfo.path))
{
RecentlyPlacedProps.Add(data.detailInfo.path);
}
}
}
public void RegisterProp(string bodyGameObjectName, GameObject prop)
{
RegisterProp_WithReturn(bodyGameObjectName, prop);
}
private PropPlacementData RegisterProp_WithReturn(string bodyGameObjectName, GameObject prop, string propPath = null, DetailInfo detailInfo = null)
{
if (Main.Debug)
{
// TOOD: make this prop an item
}
string bodyName = GetAstroObjectName(bodyGameObjectName);
Logger.Log("Adding prop to " + Main.Instance.CurrentStarSystem + "::" + bodyName);
detailInfo = detailInfo == null ? new DetailInfo() : detailInfo;
detailInfo.path = propPath == null ? currentObject : propPath;
PropPlacementData data = new PropPlacementData
{
body = bodyName,
gameObject = prop,
system = Main.Instance.CurrentStarSystem,
detailInfo = detailInfo
};
props.Add(data);
return data;
}
public Dictionary<string, DetailInfo[]> GetPropsConfigByBody()
{
var groupedProps = props
.GroupBy(p => p.system + "." + p.body)
.Select(grp => grp.ToList())
.ToList();
Dictionary<string, DetailInfo[]> propConfigs = new Dictionary<string, DetailInfo[]>();
foreach (List<PropPlacementData> bodyProps in groupedProps)
{
if (bodyProps == null || bodyProps.Count == 0) continue;
Logger.Log("getting prop group for body " + bodyProps[0].body);
if (AstroObjectLocator.GetAstroObject(bodyProps[0].body) == null) continue;
string bodyName = GetAstroObjectName(bodyProps[0].body);
DetailInfo[] infoArray = new DetailInfo[bodyProps.Count];
propConfigs[bodyName] = infoArray;
for(int i = 0; i < bodyProps.Count; i++)
{
var prop = bodyProps[i];
var rootTransform = prop.gameObject.transform.root;
// Objects are parented to the sector and not to the planet
// However, raycasted positions are reported relative to the root game object
// Normally these two are the same, but there are some notable exceptions (ex, floating islands)
// So we can't use local position/rotation here, we have to inverse transform the global position/rotation relative to root object
prop.detailInfo.position = rootTransform.InverseTransformPoint(prop.gameObject.transform.position);
prop.detailInfo.scale = prop.gameObject.transform.localScale.x;
if (!prop.detailInfo.alignToNormal) prop.detailInfo.rotation = rootTransform.InverseTransformRotation(prop.gameObject.transform.rotation).eulerAngles;
infoArray[i] = prop.detailInfo;
}
}
return propConfigs;
}
public void DeleteLast()
{
if (props.Count <= 0) return;
PropPlacementData last = props[props.Count-1];
props.RemoveAt(props.Count-1);
last.gameObject.SetActive(false);
deletedProps.Add(last);
}
public void UndoDelete()
{
if (deletedProps.Count <= 0) return;
PropPlacementData last = deletedProps[deletedProps.Count-1];
deletedProps.RemoveAt(deletedProps.Count-1);
last.gameObject.SetActive(true);
props.Add(last);
}
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Utility.DebugUtilities
{
struct DebugRaycastData
{
public bool hit;
public Vector3 pos;
public Vector3 norm;
public string bodyName;
public string bodyPath;
public GameObject hitObject;
}
}

View File

@ -0,0 +1,78 @@
using UnityEngine;
using UnityEngine.InputSystem;
namespace NewHorizons.Utility.DebugUtilities
{
[RequireComponent(typeof(OWRigidbody))]
public class DebugRaycaster : MonoBehaviour
{
private OWRigidbody _rb;
private GameObject _surfaceSphere;
private GameObject _normalSphere1;
private GameObject _normalSphere2;
private void Awake()
{
_rb = this.GetRequiredComponent<OWRigidbody>();
}
private void Update()
{
if (!Main.Debug) return;
if (Keyboard.current == null) return;
if (Keyboard.current[Key.P].wasReleasedThisFrame)
{
PrintRaycast();
}
}
internal void PrintRaycast()
{
DebugRaycastData data = Raycast();
var posText = $"{{\"x\": {data.pos.x}, \"y\": {data.pos.y}, \"z\": {data.pos.z}}}";
var normText = $"{{\"x\": {data.norm.x}, \"y\": {data.norm.y}, \"z\": {data.norm.z}}}";
if(_surfaceSphere != null) GameObject.Destroy(_surfaceSphere);
if(_normalSphere1 != null) GameObject.Destroy(_normalSphere1);
if(_normalSphere2 != null) GameObject.Destroy(_normalSphere2);
_surfaceSphere = AddDebugShape.AddSphere(data.hitObject, 0.1f, Color.green);
_normalSphere1 = AddDebugShape.AddSphere(data.hitObject, 0.01f, Color.red);
_normalSphere2 = AddDebugShape.AddSphere(data.hitObject, 0.01f, Color.red);
_surfaceSphere.transform.localPosition = data.pos;
_normalSphere1.transform.localPosition = data.pos + data.norm * 0.5f;
_normalSphere2.transform.localPosition = data.pos + data.norm;
Logger.Log($"Raycast hit \"position\": {posText}, \"normal\": {normText} on [{data.bodyName}] at [{data.bodyPath}]");
}
internal DebugRaycastData Raycast()
{
DebugRaycastData data = new DebugRaycastData();
_rb.DisableCollisionDetection();
int layerMask = OWLayerMask.physicalMask;
var origin = Locator.GetActiveCamera().transform.position;
var direction = Locator.GetActiveCamera().transform.TransformDirection(Vector3.forward);
data.hit = Physics.Raycast(origin, direction, out RaycastHit hitInfo, 100f, layerMask);
if (data.hit)
{
data.pos = hitInfo.transform.InverseTransformPoint(hitInfo.point);
data.norm = hitInfo.transform.InverseTransformDirection(hitInfo.normal);
var o = hitInfo.transform.gameObject;
data.bodyName = o.name;
data.bodyPath = SearchUtilities.GetPath(o.transform);
data.hitObject = hitInfo.transform.gameObject;
}
_rb.EnableCollisionDetection();
return data;
}
}
}

View File

@ -3,7 +3,8 @@ using OWML.Common;
using OWML.Common.Menus;
using System;
using UnityEngine;
namespace NewHorizons.Utility
namespace NewHorizons.Utility.DebugUtilities
{
public static class DebugReload
{

View File

@ -293,5 +293,19 @@ namespace NewHorizons.Utility
return new Color(r / 255, g / 255, b / 255);
}
public static Texture2D MakeSolidColorTexture(int width, int height, Color color)
{
Color[] pixels = new Color[width*height];
for(int i = 0; i < pixels.Length; i++)
{
pixels[i] = color;
}
Texture2D newTexture = new Texture2D(width, height);
newTexture.SetPixels(pixels);
newTexture.Apply();
return newTexture;
}
}
}

View File

@ -14,7 +14,7 @@ namespace NewHorizons.Utility
public int R { get; }
public int G { get; }
public int B { get; }
public int A { get; }
public int A { get; }
public Color32 ToColor32() => new Color32((byte)R, (byte)G, (byte)B, (byte)A);

View File

@ -1,19 +1,21 @@
using NewHorizons.External.Configs;
using OWML.Common;
using UnityEngine;
namespace NewHorizons.Utility
{
public class NewHorizonsBody
{
public NewHorizonsBody(PlanetConfig config, IModBehaviour mod)
{
Config = config;
Mod = mod;
}
public PlanetConfig Config;
public IModBehaviour Mod;
public GameObject Object;
}
}
using NewHorizons.External.Configs;
using OWML.Common;
using UnityEngine;
namespace NewHorizons.Utility
{
public class NewHorizonsBody
{
public NewHorizonsBody(PlanetConfig config, IModBehaviour mod, string relativePath = null)
{
Config = config;
Mod = mod;
RelativePath = relativePath;
}
public PlanetConfig Config;
public IModBehaviour Mod;
public string RelativePath;
public GameObject Object;
}
}

View File

@ -135,7 +135,7 @@ namespace NewHorizons.Utility
// Get the root object and hope its the right one
var root = GameObject.Find(names[0]);
if (root == null) root = FindObjectOfTypeAndName<GameObject>(names[0]);
if (root == null) root = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects().Where(x => x.name.Equals(names[0])).FirstOrDefault();
var t = root?.transform;
if (t == null)

50
docs/Pipfile.lock generated
View File

@ -35,10 +35,11 @@
},
"certifi": {
"hashes": [
"sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872",
"sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"
"sha256:9c5705e395cd70084351dd8ad5c41e65655e08ce46f2ec9cf6c2c08390f71eb7",
"sha256:f1d53542ee8cbedbe2118b5686372fb33c297fcd6379b050cca0ef13a597382a"
],
"version": "==2021.10.8"
"markers": "python_version >= '3.6'",
"version": "==2022.5.18.1"
},
"charset-normalizer": {
"hashes": [
@ -111,11 +112,11 @@
},
"json-schema-for-humans": {
"hashes": [
"sha256:a96f7bb1175bf979ac6360a0dbea81a82443abdb376696dc33f5a6fb8705f25e",
"sha256:e05f0d52d6ac211eceecd5201bcefb91538c9b75ecb56a1950b47090ac3ab8b6"
"sha256:030650ab4457556d09867d1b503619652dccf1c3ae118343663848faded97fc0",
"sha256:7ea6998e6c86c724c0693ec7379559b1b568309c3500e0d64ced56b31b778fa2"
],
"markers": "python_version >= '3.7' and python_version < '4'",
"version": "==0.40.5"
"markers": "python_version >= '3.7' and python_version < '4.0'",
"version": "==0.41.1"
},
"jsonschema": {
"hashes": [
@ -125,6 +126,21 @@
"markers": "python_version >= '3.7'",
"version": "==4.5.1"
},
"libsass": {
"hashes": [
"sha256:06c8776417fe930714bdc930a3d7e795ae3d72be6ac883ff72a1b8f7c49e5ffb",
"sha256:12f39712de38689a8b785b7db41d3ba2ea1d46f9379d81ea4595802d91fa6529",
"sha256:1e25dd9047a9392d3c59a0b869e0404f2b325a03871ee45285ee33b3664f5613",
"sha256:659ae41af8708681fa3ec73f47b9735a6725e71c3b66ff570bfce78952f2314e",
"sha256:6b984510ed94993708c0d697b4fef2d118929bbfffc3b90037be0f5ccadf55e7",
"sha256:a005f298f64624f313a3ac618ab03f844c71d84ae4f4a4aec4b68d2a4ffe75eb",
"sha256:abc29357ee540849faf1383e1746d40d69ed5cb6d4c346df276b258f5aa8977a",
"sha256:c9ec490609752c1d81ff6290da33485aa7cb6d7365ac665b74464c1b7d97f7da",
"sha256:d5ba529d9ce668be9380563279f3ffe988f27bc5b299c5a28453df2e0b0fbaf2",
"sha256:e2b1a7d093f2e76dc694c17c0c285e846d0b0deb0e8b21dc852ba1a3a4e2f1d6"
],
"version": "==0.21.0"
},
"markdown": {
"hashes": [
"sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874",
@ -138,7 +154,7 @@
"sha256:412520c7b6bba540c2c2067d6be3a523ab885703bf6a81d93963f848b55dfb9a",
"sha256:f344d4adfba5d1de821f7850b36e3507f583468a7eb47e6fa191765ed0b9c66b"
],
"markers": "python_version >= '3.5' and python_version < '4'",
"markers": "python_version >= '3.5' and python_version < '4.0'",
"version": "==2.4.3"
},
"markupsafe": {
@ -204,11 +220,11 @@
},
"menagerie-docs": {
"hashes": [
"sha256:6edf3371d1b4c0ac42dc1bde72b46dbfef7d96b1065d1d605fcd07af1d6c8e9a",
"sha256:fc8da001ff050859d74c6b5cdcdf887c5aa47e2b263271ab20554010fd72337d"
"sha256:5f02204f4c8a6a3eee947ee4c91266159b567fd8e22d69be43531ef2e4a99f6a",
"sha256:ad69a97a65a73ad3f2be0f28638b74d1a6af68a5ce00c7b9726a9e0e89bb3d82"
],
"index": "pypi",
"version": "==0.1.5"
"version": "==0.1.8"
},
"mypy-extensions": {
"hashes": [
@ -222,7 +238,7 @@
"sha256:5053fc5ca7b8a281081274702ebf1584e341f40a68e6ab8f6b4b79f4b3fdf18e",
"sha256:8e8226f15c0b25565aa391797963b78c95930e12efc40e905153130783e766be"
],
"markers": "python_version >= '3.8' and python_version < '4'",
"markers": "python_version >= '3.8' and python_version < '4.0'",
"version": "==0.1.0"
},
"packaging": {
@ -424,6 +440,14 @@
],
"version": "==1.2.0"
},
"six": {
"hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0"
},
"soupsieve": {
"hashes": [
"sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759",
@ -453,7 +477,7 @@
"sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14",
"sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'",
"version": "==1.26.9"
},
"xmlschema": {

View File

@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/Bwc9876/menagerie/master/menagerie/schemas/config_schema.json",
"cache_enabled": true,
"cache_enabled": false,
"base_url": "https://nh.outerwildsmods.com/",
"themes": {
"bootstrap": "https://bootswatch.com/5/darkly/bootstrap.min.css",
@ -8,8 +8,7 @@
"theme": "dark"
},
"styles": {
"base": "styles/base.css",
"schema": "styles/schema.css"
"base": "styles/nh_base.css"
},
"search": {
"enabled": true,

View File

@ -145,3 +145,13 @@ These tools/references are highly recommended
- [XML Basics Tutorial](https://www.w3schools.com/xml/xml_whatis.asp){ target="_blank" }
- [JSON Basics Tutorial](https://www.tutorialspoint.com/json/index.htm){ target="_blank" }
- [The Examples Mod](https://github.com/xen-42/ow-new-horizons-examples){ target="_blank" }
## Disclaimer
This work is unofficial fan content created under permission from the [Mobius Digital Fan Content Policy](https://www.mobiusdigitalgames.com/fan-content-policy.html). It includes materials which are the property of Mobius Digital, and it is neither approved nor endorsed by Mobius Digital.
We are not responsible for any mods created using the New Horizons modding framework and assume no responsibility in the event an addon violates the terms.
## License
The license for this project is available [on the GitHub repository](https://github.com/xen-42/outer-wilds-new-horizons/blob/main/LICENSE).

View File

@ -1,55 +0,0 @@
$(document).on('click', 'a[href^="#"]', function (event) {
if (this.href.split("#")[1] === "top") return;
event.preventDefault();
history.pushState({}, '', this.href);
});
function flashElement(elementId) {
myElement = document.getElementById(elementId).parentNode;
myElement.classList.add("jsfh-animated-property");
setTimeout(function () {
myElement.classList.remove("jsfh-animated-property");
}, 1000);
}
function setAnchor(anchorLinkDestination) {
history.pushState({}, '', anchorLinkDestination);
}
function anchorOnLoad() {
let linkTarget = window.location.hash.split("?")[0].split("&")[0];
if (linkTarget[0] === "#") {
let idTarget = linkTarget.substring(1);
if (idTarget !== "top") {
anchorLink(idTarget);
}
}
}
function anchorLink(linkTarget) {
const target = $("#" + linkTarget);
target.parents().addBack().filter(".collapse:not(.show), .tab-pane, [role='tab']").each(
function (index) {
if ($(this).hasClass("collapse")) {
$(this).collapse("show");
} else if ($(this).hasClass("tab-pane")) {
const tabToShow = $("a[href='#" + $(this).attr("id") + "']");
if (tabToShow) {
tabToShow.tab("show");
}
} else if ($(this).attr("role") === "tab") {
$(this).tab("show");
}
}
);
setTimeout(function () {
let targetElement = document.getElementById(linkTarget);
if (targetElement) {
targetElement.scrollIntoView({block: "center", behavior: "smooth"});
setTimeout(function () {
flashElement(linkTarget);
}, 500);
}
}, 1000);
}

View File

@ -1,19 +0,0 @@
.jsfh-animated-property {
animation: eclair;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-duration: .75s;
}
@keyframes eclair {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.03);
}
}
.bg-warning {
color: #131313;
}