Merge remote-tracking branch 'isle/master'
Some checks are pending
CI / clang-format (push) Waiting to run
CI / ${{ matrix.name }} (false, --toolchain /usr/local/vitasdk/share/vita.toolchain.cmake, false, false, Ninja, Vita, ubuntu-latest, true, true) (push) Waiting to run
CI / ${{ matrix.name }} (false, -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0.26100.0, false, false, Visual Studio 17 2022, true, Xbox One, windows-latest, amd64, false, true) (push) Waiting to run
CI / ${{ matrix.name }} (false, -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/3DS.cmake, false, devkitpro/devkitarm:latest, false, Ninja, true, Nintendo 3DS, ubuntu-latest, true) (push) Waiting to run
CI / ${{ matrix.name }} (false, -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake, false, devkitpro/devkita64:latest, false, Ninja, Nintendo Switch, true, ubuntu-latest, true) (push) Waiting to run
CI / ${{ matrix.name }} (false, emcmake, false, false, true, Ninja, Emscripten, ubuntu-latest, true) (push) Waiting to run
CI / ${{ matrix.name }} (false, false, false, Ninja, true, MSVC (arm64), windows-latest, amd64_arm64, false) (push) Waiting to run
CI / ${{ matrix.name }} (false, false, true, Ninja, true, MSVC (x86), windows-latest, amd64_x86, false) (push) Waiting to run
CI / ${{ matrix.name }} (false, true, false, Ninja, true, MSVC (x64), windows-latest, amd64, false) (push) Waiting to run
CI / ${{ matrix.name }} (false, true, true, false, Ninja, true, MSVC (x64 Debug), windows-latest, amd64, false) (push) Waiting to run
CI / ${{ matrix.name }} (true, false, -DCMAKE_SYSTEM_NAME=iOS, false, false, Xcode, true, iOS, macos-15, true) (push) Waiting to run
CI / ${{ matrix.name }} (true, false, false, Ninja, true, mingw-w64-i686, mingw32, msys2 mingw32, windows-latest, msys2 {0}, true) (push) Waiting to run
CI / ${{ matrix.name }} (true, false, false, false, Ninja, Android, ubuntu-latest, true) (push) Waiting to run
CI / ${{ matrix.name }} (true, false, true, false, Ninja, macOS, macos-latest, true) (push) Waiting to run
CI / ${{ matrix.name }} (true, true, false, Ninja, true, mingw-w64-x86_64, mingw64, msys2 mingw64, windows-latest, msys2 {0}, true) (push) Waiting to run
CI / ${{ matrix.name }} (true, true, true, false, Ninja, true, Linux (Debug), ubuntu-latest, true) (push) Waiting to run
CI / ${{ matrix.name }} (true, true, true, false, Ninja, true, Linux, ubuntu-latest, true) (push) Waiting to run
CI / Flatpak (${{ matrix.arch }}) (aarch64, ubuntu-22.04-arm) (push) Waiting to run
CI / Flatpak (${{ matrix.arch }}) (x86_64, ubuntu-latest) (push) Waiting to run
CI / C++ (push) Waiting to run
CI / Release (push) Blocked by required conditions
Docker / Publish web port (push) Waiting to run

This commit is contained in:
Christian Semmler 2026-01-30 17:05:27 -08:00
commit a3122cd209
No known key found for this signature in database
GPG Key ID: 086DAA1360BEEE5C
87 changed files with 3268 additions and 2278 deletions

635
.pylintrc
View File

@ -1,635 +0,0 @@
[MAIN]
# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no
# Clear in-memory caches upon conclusion of linting. Useful if running pylint
# in a server-like mode.
clear-cache-post-run=no
# Load and enable all available extensions. Use --list-extensions to see a list
# all available extensions.
#enable-all-extensions=
# In error mode, messages with a category besides ERROR or FATAL are
# suppressed, and no reports are done by default. Error mode is compatible with
# disabling specific errors.
#errors-only=
# Always return a 0 (non-error) status code, even if lint errors are found.
# This is primarily useful in continuous integration scripts.
#exit-zero=
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code.
extension-pkg-allow-list=
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code. (This is an alternative name to extension-pkg-allow-list
# for backward compatibility.)
extension-pkg-whitelist=
# Return non-zero exit code if any of these messages/categories are detected,
# even if score is above --fail-under value. Syntax same as enable. Messages
# specified are enabled, while categories only check already-enabled messages.
fail-on=
# Specify a score threshold under which the program will exit with error.
fail-under=10
# Interpret the stdin as a python script, whose filename needs to be passed as
# the module_or_package argument.
#from-stdin=
# Files or directories to be skipped. They should be base names, not paths.
ignore=CVS
# Add files or directories matching the regular expressions patterns to the
# ignore-list. The regex matches against paths and can be in Posix or Windows
# format. Because '\\' represents the directory delimiter on Windows systems,
# it can't be used as an escape character.
ignore-paths=
# Files or directories matching the regular expression patterns are skipped.
# The regex matches against base names, not paths. The default value ignores
# Emacs file locks
ignore-patterns=^\.#
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis). It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
# number of processors available to use, and will cap the count on Windows to
# avoid hangs.
jobs=1
# Control the amount of potential inferred values when inferring a single
# object. This can help the performance when dealing with large functions or
# complex, nested conditions.
limit-inference-results=100
# List of plugins (as comma separated values of python module names) to load,
# usually to register additional checkers.
load-plugins=
# Pickle collected data for later comparisons.
persistent=yes
# Minimum Python version to use for version dependent checks. Will default to
# the version used to run pylint.
py-version=3.12
# Discover python modules and packages in the file system subtree.
recursive=no
# Add paths to the list of the source roots. Supports globbing patterns. The
# source root is an absolute path or a path relative to the current working
# directory used to determine a package namespace for modules located under the
# source root.
source-roots=
# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages.
suggestion-mode=yes
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
# In verbose mode, extra non-checker-related info will be displayed.
#verbose=
[BASIC]
# Naming style matching correct argument names.
argument-naming-style=snake_case
# Regular expression matching correct argument names. Overrides argument-
# naming-style. If left empty, argument names will be checked with the set
# naming style.
#argument-rgx=
# Naming style matching correct attribute names.
attr-naming-style=snake_case
# Regular expression matching correct attribute names. Overrides attr-naming-
# style. If left empty, attribute names will be checked with the set naming
# style.
#attr-rgx=
# Bad variable names which should always be refused, separated by a comma.
bad-names=foo,
bar,
baz,
toto,
tutu,
tata
# Bad variable names regexes, separated by a comma. If names match any regex,
# they will always be refused
bad-names-rgxs=
# Naming style matching correct class attribute names.
class-attribute-naming-style=any
# Regular expression matching correct class attribute names. Overrides class-
# attribute-naming-style. If left empty, class attribute names will be checked
# with the set naming style.
#class-attribute-rgx=
# Naming style matching correct class constant names.
class-const-naming-style=UPPER_CASE
# Regular expression matching correct class constant names. Overrides class-
# const-naming-style. If left empty, class constant names will be checked with
# the set naming style.
#class-const-rgx=
# Naming style matching correct class names.
class-naming-style=PascalCase
# Regular expression matching correct class names. Overrides class-naming-
# style. If left empty, class names will be checked with the set naming style.
#class-rgx=
# Naming style matching correct constant names.
const-naming-style=UPPER_CASE
# Regular expression matching correct constant names. Overrides const-naming-
# style. If left empty, constant names will be checked with the set naming
# style.
#const-rgx=
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
# Naming style matching correct function names.
function-naming-style=snake_case
# Regular expression matching correct function names. Overrides function-
# naming-style. If left empty, function names will be checked with the set
# naming style.
#function-rgx=
# Good variable names which should always be accepted, separated by a comma.
good-names=i,
j,
k,
ex,
Run,
_
# Good variable names regexes, separated by a comma. If names match any regex,
# they will always be accepted
good-names-rgxs=
# Include a hint for the correct naming format with invalid-name.
include-naming-hint=no
# Naming style matching correct inline iteration names.
inlinevar-naming-style=any
# Regular expression matching correct inline iteration names. Overrides
# inlinevar-naming-style. If left empty, inline iteration names will be checked
# with the set naming style.
#inlinevar-rgx=
# Naming style matching correct method names.
method-naming-style=snake_case
# Regular expression matching correct method names. Overrides method-naming-
# style. If left empty, method names will be checked with the set naming style.
#method-rgx=
# Naming style matching correct module names.
module-naming-style=snake_case
# Regular expression matching correct module names. Overrides module-naming-
# style. If left empty, module names will be checked with the set naming style.
#module-rgx=
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_
# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties.
# These decorators are taken in consideration only for invalid-name.
property-classes=abc.abstractproperty
# Regular expression matching correct type alias names. If left empty, type
# alias names will be checked with the set naming style.
#typealias-rgx=
# Regular expression matching correct type variable names. If left empty, type
# variable names will be checked with the set naming style.
#typevar-rgx=
# Naming style matching correct variable names.
variable-naming-style=snake_case
# Regular expression matching correct variable names. Overrides variable-
# naming-style. If left empty, variable names will be checked with the set
# naming style.
#variable-rgx=
[CLASSES]
# Warn about protected attribute access inside special methods
check-protected-access-in-special-methods=no
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,
__new__,
setUp,
asyncSetUp,
__post_init__
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
[DESIGN]
# List of regular expressions of class ancestor names to ignore when counting
# public methods (see R0903)
exclude-too-few-public-methods=
# List of qualified class names to ignore when counting class parents (see
# R0901)
ignored-parents=
# Maximum number of arguments for function / method.
max-args=6
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Maximum number of boolean expressions in an if statement (see R0916).
max-bool-expr=5
# Maximum number of branch for function / method body.
max-branches=30
# Maximum number of locals for function / method body.
max-locals=30
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of return / yield for function / method body.
max-returns=6
# Maximum number of statements in function / method body.
max-statements=75
# Minimum number of public methods for a class (see R0903).
min-public-methods=0
[EXCEPTIONS]
# Exceptions that will emit a warning when caught.
overgeneral-exceptions=builtins.BaseException,builtins.Exception
[FORMAT]
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=2
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Maximum number of characters on a single line.
max-line-length=200
# Maximum number of lines in a module.
max-module-lines=1000
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
[IMPORTS]
# List of modules that can be imported at any level, not just the top level
# one.
allow-any-import-level=
# Allow explicit reexports by alias from a package __init__.
allow-reexport-from-package=no
# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no
# Deprecated modules which should not be used, separated by a comma.
deprecated-modules=
# Output a graph (.gv or any supported image format) of external dependencies
# to the given file (report RP0402 must not be disabled).
ext-import-graph=
# Output a graph (.gv or any supported image format) of all (i.e. internal and
# external) dependencies to the given file (report RP0402 must not be
# disabled).
import-graph=
# Output a graph (.gv or any supported image format) of internal dependencies
# to the given file (report RP0402 must not be disabled).
int-import-graph=
# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=
# Force import order to recognize a module as part of a third party library.
known-third-party=enchant
# Couples of modules and preferred modules, separated by a comma.
preferred-modules=
[LOGGING]
# The type of string formatting that logging methods do. `old` means using %
# formatting, `new` is for `{}` formatting.
logging-format-style=old
# Logging modules to check that the string format arguments are in logging
# function parameter format.
logging-modules=logging
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
# UNDEFINED.
confidence=HIGH,
CONTROL_FLOW,
INFERENCE,
INFERENCE_FAILURE,
UNDEFINED
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once). You can also use "--disable=all" to
# disable everything first and then re-enable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable=raw-checker-failed,
bad-inline-option,
locally-disabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
use-symbolic-message-instead,
missing-class-docstring,
missing-function-docstring,
missing-module-docstring,
fixme
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=c-extension-no-member
[METHOD_ARGS]
# List of qualified names (i.e., library.method) which require a timeout
# parameter e.g. 'requests.api.get,requests.api.post'
timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,
XXX,
TODO
# Regular expression of note tags to take in consideration.
notes-rgx=
[REFACTORING]
# Maximum number of nested blocks for function / method body
max-nested-blocks=5
# Complete name of functions that never returns. When checking for
# inconsistent-return-statements if a never returning function is called then
# it will be considered as an explicit return statement and no message will be
# printed.
never-returning-functions=sys.exit,argparse.parse_error
[REPORTS]
# Python expression which should return a score less than or equal to 10. You
# have access to the variables 'fatal', 'error', 'warning', 'refactor',
# 'convention', and 'info' which contain the number of messages in each
# category, as well as 'statement' which is the total number of statements
# analyzed. This score is used by the global evaluation report (RP0004).
evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details.
msg-template=
# Set the output format. Available formats are text, parseable, colorized, json
# and msvs (visual studio). You can also give a reporter class, e.g.
# mypackage.mymodule.MyReporterClass.
#output-format=
# Tells whether to display a full report or only the messages.
reports=no
# Activate the evaluation score.
score=yes
[SIMILARITIES]
# Comments are removed from the similarity computation
ignore-comments=yes
# Docstrings are removed from the similarity computation
ignore-docstrings=yes
# Imports are removed from the similarity computation
ignore-imports=yes
# Signatures are removed from the similarity computation
ignore-signatures=yes
# Minimum lines number of a similarity.
min-similarity-lines=16
[SPELLING]
# Limits count of emitted suggestions for spelling mistakes.
max-spelling-suggestions=4
# Spelling dictionary name. No available dictionaries : You need to install
# both the python package and the system dependency for enchant to work..
spelling-dict=
# List of comma separated words that should be considered directives if they
# appear at the beginning of a comment and should not be checked.
spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains the private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to the private dictionary (see the
# --spelling-private-dict-file option) instead of raising a message.
spelling-store-unknown-words=no
[STRING]
# This flag controls whether inconsistent-quotes generates a warning when the
# character used as a quote delimiter is used inconsistently within a module.
check-quote-consistency=no
# This flag controls whether the implicit-str-concat should generate a warning
# on implicit string concatenation in sequences defined over several lines.
check-str-concat-over-line-jumps=no
[TYPECHECK]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
# Tells whether to warn about missing members when the owner of the attribute
# is inferred to be None.
ignore-none=yes
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes
# List of symbolic message names to ignore for Mixin members.
ignored-checks-for-mixins=no-member,
not-async-context-manager,
not-context-manager,
attribute-defined-outside-init
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace
# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes
# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1
# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1
# Regex pattern to define which classes are considered mixins.
mixin-class-rgx=.*[Mm]ixin
# List of decorators that change the signature of a decorated function.
signature-mutators=
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid defining new builtins when possible.
additional-builtins=
# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes
# List of names allowed to shadow builtins
allowed-redefined-builtins=
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,
_cb
# A regular expression matching the name of dummy variables (i.e. expected to
# not be used).
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
# Argument names that match this expression will be ignored.
ignored-argument-names=_.*|^ignored_|^unused_
# Tells whether we should check for unused import in __init__ files.
init-import=no
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io

View File

@ -310,7 +310,7 @@ target_sources(lego1 PRIVATE
LEGO1/lego/sources/misc/legostorage.cpp
LEGO1/lego/sources/misc/legotexture.cpp
LEGO1/lego/sources/misc/legotree.cpp
LEGO1/lego/sources/misc/legounknown.cpp
LEGO1/lego/sources/misc/legospline.cpp
)
target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1/omni/include" "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/LEGO1/lego/sources")

View File

@ -29,18 +29,18 @@ class Act2Actor : public LegoAnimActor {
void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30
// FUNCTION: LEGO1 0x1001a180
MxS32 VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3) override
MxS32 CheckIntersections(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3) override
{
if (m_animatingHit) {
return 0;
}
return LegoAnimActor::VTable0x68(p_v1, p_v2, p_v3);
return LegoAnimActor::CheckIntersections(p_v1, p_v2, p_v3);
} // vtable+0x68
void Animate(float p_time) override; // vtable+0x70
MxResult HitActor(LegoPathActor*, MxBool) override; // vtable+0x94
MxResult VTable0x9c() override; // vtable+0x9c
MxResult CalculateSpline() override; // vtable+0x9c
MxS32 NextTargetLocation() override; // vtable+0xa0
void InitializeNextShot();

View File

@ -57,7 +57,7 @@ class Act3Actor : public LegoAnimActor {
public:
Act3Actor();
MxU32 VTable0x90(float p_time, Matrix4& p_transform) override; // vtable+0x90
MxU32 StepState(float p_time, Matrix4& p_transform) override; // vtable+0x90
MxResult HitActor(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94
// FUNCTION: LEGO1 0x100431b0
@ -105,7 +105,7 @@ class Act3Cop : public Act3Actor {
void ParseAction(char* p_extra) override; // vtable+0x20
void Animate(float p_time) override; // vtable+0x70
MxResult HitActor(LegoPathActor*, MxBool) override; // vtable+0x94
MxResult VTable0x9c() override; // vtable+0x9c
MxResult CalculateSpline() override; // vtable+0x9c
MxFloat GetUnknown0x20() { return m_unk0x20; }
@ -142,8 +142,8 @@ class Act3Brickster : public Act3Actor {
LegoPathBoundary*& p_boundary,
LegoOrientedEdge*& p_edge,
float& p_unk0xe4
) override; // vtable+0x98
MxResult VTable0x9c() override; // vtable+0x9c
) override; // vtable+0x98
MxResult CalculateSpline() override; // vtable+0x9c
MxFloat GetUnknown0x20() { return m_unk0x20; }
MxFloat GetUnknown0x24() { return m_unk0x24; }

View File

@ -14,7 +14,7 @@ class Act3Ammo : public LegoPathActor {
c_pizza = 0x01,
c_donut = 0x02,
c_valid = 0x04,
c_bit4 = 0x08,
c_withoutBoundary = 0x08,
c_sharkFood = 0x10
};
@ -28,10 +28,10 @@ class Act3Ammo : public LegoPathActor {
MxU32 IsValid() { return m_ammoFlag & c_valid; }
// FUNCTION: BETA10 0x100177b0
Mx3DPointFloat* GetUnknown0x160() { return m_eq; }
Mx3DPointFloat* GetCoefficients() { return m_coefficients; }
// FUNCTION: BETA10 0x100177e0
MxFloat* GetUnknown0x19c() { return &m_unk0x19c; }
MxFloat* GetApexParameter() { return &m_apexParameter; }
// FUNCTION: BETA10 0x1001fbd0
void SetValid(MxBool p_valid)
@ -51,18 +51,18 @@ class Act3Ammo : public LegoPathActor {
MxU32 IsDonut() { return m_ammoFlag & c_donut; }
// FUNCTION: BETA10 0x1001fcb0
void SetBit4(MxBool p_bit4)
void SetShootWithoutBoundary(MxBool p_withoutBoundary)
{
if (p_bit4) {
m_ammoFlag |= c_bit4;
if (p_withoutBoundary) {
m_ammoFlag |= c_withoutBoundary;
}
else {
m_ammoFlag &= ~c_bit4;
m_ammoFlag &= ~c_withoutBoundary;
}
}
// FUNCTION: BETA10 0x10021d90
MxU32 IsBit4() { return m_ammoFlag & c_bit4; }
MxU32 IsShootWithoutBoundary() { return m_ammoFlag & c_withoutBoundary; }
void SetSharkFood(MxBool p_sharkFood)
{
@ -76,29 +76,29 @@ class Act3Ammo : public LegoPathActor {
MxU32 IsSharkFood() { return m_ammoFlag & c_sharkFood; }
MxFloat GetUnknown0x158() { return m_unk0x158; }
MxFloat GetRotateTimeout() { return m_rotateTimeout; }
void SetUnknown0x158(MxFloat p_unk0x158) { m_unk0x158 = p_unk0x158; }
void SetRotateTimeout(MxFloat p_rotateTimeout) { m_rotateTimeout = p_rotateTimeout; }
MxResult Remove();
MxResult Create(Act3* p_world, MxU32 p_isPizza, MxS32 p_index);
MxResult FUN_10053b40(const Vector3& p_srcLoc, const Vector3& p_srcDir, const Vector3& p_srcUp);
MxResult FUN_10053cb0(LegoPathController* p_p, LegoPathBoundary* p_boundary, MxFloat p_unk0x19c);
MxResult FUN_10053d30(LegoPathController* p_p, MxFloat p_unk0x19c);
MxResult CalculateArc(const Vector3& p_srcLoc, const Vector3& p_srcDir, const Vector3& p_srcUp);
MxResult Shoot(LegoPathController* p_p, LegoPathBoundary* p_boundary, MxFloat p_apexParameter);
MxResult Shoot(LegoPathController* p_p, MxFloat p_apexParameter);
// SYNTHETIC: LEGO1 0x10053880
// Act3Ammo::`scalar deleting destructor'
private:
MxResult FUN_10053db0(float p_param1, Matrix4& p_param2);
MxResult CalculateTransformOnCurve(float p_curveParameter, Matrix4& p_transform);
static Mx3DPointFloat g_unk0x10104f08;
static Mx3DPointFloat g_hitTranslation;
MxU16 m_ammoFlag; // 0x154
MxFloat m_unk0x158; // 0x158
Act3* m_world; // 0x15c
Mx3DPointFloat m_eq[3]; // 0x160
MxFloat m_unk0x19c; // 0x19c
MxU16 m_ammoFlag; // 0x154
MxFloat m_rotateTimeout; // 0x158
Act3* m_world; // 0x15c
Mx3DPointFloat m_coefficients[3]; // 0x160
MxFloat m_apexParameter; // 0x19c
};
#endif // ACT3AMMO_H

View File

@ -10,7 +10,7 @@ class LegoROI;
// SIZE 0x1f8
class Doors : public LegoPathActor {
public:
Doors() : m_unk0x154(0), m_ltDoor(NULL), m_rtDoor(NULL), m_unk0x1f4(0) {}
Doors() : m_state(0), m_ltDoor(NULL), m_rtDoor(NULL), m_angle(0) {}
// FUNCTION: LEGO1 0x1000e430
// FUNCTION: BETA10 0x100a7f20
@ -29,19 +29,25 @@ class Doors : public LegoPathActor {
void ParseAction(char* p_extra) override; // vtable+0x20
void Animate(float p_time) override; // vtable+0x70
MxResult HitActor(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94
virtual MxFloat VTable0xcc(float p_time); // vtable+0xcc
virtual MxFloat CalculateAngle(float p_time); // vtable+0xcc
// SYNTHETIC: LEGO1 0x1000e580
// Doors::`scalar deleting destructor'
private:
undefined4 m_unk0x154; // 0x154
MxFloat m_unk0x158; // 0x158
LegoROI* m_ltDoor; // 0x15c
LegoROI* m_rtDoor; // 0x160
MxMatrix m_ltDoorLocal; // 0x164
MxMatrix m_rtDoorLocal; // 0x1ac
MxFloat m_unk0x1f4; // 0x1f4
enum {
e_none = 0,
e_closed = 1,
e_cycling = 2,
};
undefined4 m_state; // 0x154
MxFloat m_hitTime; // 0x158
LegoROI* m_ltDoor; // 0x15c
LegoROI* m_rtDoor; // 0x160
MxMatrix m_ltDoorOriginalLocal; // 0x164
MxMatrix m_rtDoorOriginalLocal; // 0x1ac
MxFloat m_angle; // 0x1f4
};
#endif // DOORS_H

View File

@ -69,7 +69,7 @@ class Helicopter : public IslePathActor {
MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18
void Animate(float p_time) override; // vtable+0x70
void VTable0x74(Matrix4& p_transform) override; // vtable+0x74
void ApplyTransform(Matrix4& p_transform) override; // vtable+0x74
MxLong HandleClick() override; // vtable+0xcc
MxLong HandleControl(LegoControlManagerNotificationParam& p_param) override; // vtable+0xd4
MxLong HandleEndAnim(LegoEndAnimNotificationParam& p_param) override; // vtable+0xd8

View File

@ -102,10 +102,10 @@ class IslePathActor : public LegoPathActor {
// FUNCTION: LEGO1 0x10002e00
virtual MxLong HandlePathStruct(LegoPathStructNotificationParam&) { return 0; } // vtable+0xdc
virtual void Enter(); // vtable+0xe0
virtual void Exit(); // vtable+0xe4
virtual void SpawnPlayer(LegoGameState::Area p_area, MxBool p_enter, MxU8 p_flags); // vtable+0xe8
virtual void VTable0xec(MxMatrix p_transform, LegoPathBoundary* p_boundary, MxBool p_reset); // vtable+0xec
virtual void Enter(); // vtable+0xe0
virtual void Exit(); // vtable+0xe4
virtual void SpawnPlayer(LegoGameState::Area p_area, MxBool p_enter, MxU8 p_flags); // vtable+0xe8
virtual void UpdateWorld(MxMatrix p_transform, LegoPathBoundary* p_boundary, MxBool p_reset); // vtable+0xec
// FUNCTION: LEGO1 0x10002e10
~IslePathActor() override { IslePathActor::Destroy(TRUE); }
@ -129,7 +129,7 @@ class IslePathActor : public LegoPathActor {
MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18
void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c
void FUN_1001b660();
void TurnAround();
void SetWorld(LegoWorld* p_world) { m_world = p_world; }

View File

@ -10,7 +10,7 @@
// SIZE 0x68
class LegoActionControlPresenter : public MxMediaPresenter {
public:
LegoActionControlPresenter() : m_unk0x50(Extra::ActionType::e_none) {}
LegoActionControlPresenter() : m_actionType(Extra::ActionType::e_none) {}
~LegoActionControlPresenter() override { Destroy(TRUE); } // vtable+0x00
// FUNCTION: BETA10 0x100a7840
@ -40,9 +40,9 @@ class LegoActionControlPresenter : public MxMediaPresenter {
virtual void Destroy(MxBool p_fromDestructor); // vtable+0x5c
private:
Extra::ActionType m_unk0x50; // 0x50
MxString m_unk0x54; // 0x54
undefined4 m_unk0x64; // 0x64
Extra::ActionType m_actionType; // 0x50
MxString m_sourceName; // 0x54
undefined4 m_streamId; // 0x64
};
// SYNTHETIC: LEGO1 0x1000d1d0

View File

@ -42,10 +42,10 @@ class LegoAnimActor : public virtual LegoPathActor {
~LegoAnimActor() override;
void ParseAction(char* p_extra) override; // vtable+0x20
void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30
void Animate(float p_time) override; // vtable+0x70
void VTable0x74(Matrix4& p_transform) override; // vtable+0x74
void ParseAction(char* p_extra) override; // vtable+0x20
void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30
void Animate(float p_time) override; // vtable+0x70
void ApplyTransform(Matrix4& p_transform) override; // vtable+0x74
virtual MxResult GetTimeInCycle(float& p_timeInCycle);
virtual MxResult AnimateWithTransform(float p_time, Matrix4& p_transform);

View File

@ -61,7 +61,7 @@ class LegoAnimMMPresenter : public MxCompositePresenter {
void ParseExtra() override; // vtable+0x30
MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c
void EndAction() override; // vtable+0x40
void VTable0x60(MxPresenter* p_presenter) override; // vtable+0x60
void AdvanceSerialAction(MxPresenter* p_presenter) override; // vtable+0x60
// SYNTHETIC: LEGO1 0x1004aa40
// LegoAnimMMPresenter::`scalar deleting destructor'

View File

@ -62,21 +62,27 @@ class LegoAnimPresenter : public MxVideoPresenter {
return !strcmp(p_name, LegoAnimPresenter::ClassName()) || MxVideoPresenter::IsA(p_name);
}
void ReadyTickle() override; // vtable+0x18
void StartingTickle() override; // vtable+0x1c
void StreamingTickle() override; // vtable+0x20
void DoneTickle() override; // vtable+0x2c
void ParseExtra() override; // vtable+0x30
MxResult AddToManager() override; // vtable+0x34
void Destroy() override; // vtable+0x38
MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c
void EndAction() override; // vtable+0x40
void PutFrame() override; // vtable+0x6c
virtual MxResult CreateAnim(MxStreamChunk* p_chunk); // vtable+0x88
virtual void VTable0x8c(); // vtable+0x8c
virtual void VTable0x90(); // vtable+0x90
virtual MxU32 VTable0x94(Vector3& p_v1, Vector3& p_v2, float p_f1, float p_f2, Vector3& p_v3); // vtable+0x94
virtual MxResult VTable0x98(LegoPathBoundary* p_boundary); // vtable+0x98
void ReadyTickle() override; // vtable+0x18
void StartingTickle() override; // vtable+0x1c
void StreamingTickle() override; // vtable+0x20
void DoneTickle() override; // vtable+0x2c
void ParseExtra() override; // vtable+0x30
MxResult AddToManager() override; // vtable+0x34
void Destroy() override; // vtable+0x38
MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c
void EndAction() override; // vtable+0x40
void PutFrame() override; // vtable+0x6c
virtual MxResult CreateAnim(MxStreamChunk* p_chunk); // vtable+0x88
virtual void AddToWorld(); // vtable+0x8c
virtual void RemoveFromWorld(); // vtable+0x90
virtual MxU32 Intersect(
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint
); // vtable+0x94
virtual MxResult AddActors(LegoPathBoundary* p_boundary); // vtable+0x98
// FUNCTION: LEGO1 0x1000c990
virtual LegoROI** GetROIMap(MxU32& p_roiMapSize)
@ -85,47 +91,47 @@ class LegoAnimPresenter : public MxVideoPresenter {
return m_roiMap;
} // vtable+0x9c
virtual void VTable0xa0(Matrix4& p_matrix); // vtable+0xa0
virtual void SetTransform(Matrix4& p_matrix); // vtable+0xa0
MxResult FUN_1006afc0(MxMatrix*& p_matrix, float p_und);
MxResult FUN_1006b140(LegoROI* p_roi);
void FUN_1006c7a0();
MxResult GetTransforms(MxMatrix*& p_matrix, float p_time);
MxResult CopyTransform(LegoROI* p_roi);
void ApplyFinishedTransform();
const char* GetActionObjectName();
void SetCurrentWorld(LegoWorld* p_currentWorld) { m_currentWorld = p_currentWorld; }
// FUNCTION: BETA10 0x1005aad0
void SetUnknown0x0cTo1() { m_unk0x9c = 1; }
void SetRoiTransformApplied() { m_roiTransformApplied = 1; }
// FUNCTION: BETA10 0x1005ab00
void SetUnknown0xa0(Matrix4* p_unk0xa0) { m_unk0xa0 = p_unk0xa0; }
void SetRoiTransform(Matrix4* p_roiTransform) { m_roiTransform = p_roiTransform; }
LegoAnim* GetAnimation() { return m_anim; }
protected:
void Init();
void Destroy(MxBool p_fromDestructor);
LegoChar* FUN_10069150(const LegoChar* p_und1);
void FUN_100692b0();
void FUN_100695c0();
LegoChar* GetActorName(const LegoChar* p_name);
void CreateManagedActors();
void CreateSceneROIs();
LegoChar* GetVariableOrIdentity(const LegoChar* p_varName, const LegoChar* p_prefix);
LegoBool FUN_100698b0(const CompoundObject& p_rois, const LegoChar* p_und2);
LegoBool AppendROIToScene(const CompoundObject& p_rois, const LegoChar* p_varName);
LegoROI* FindROI(const LegoChar* p_name);
void FUN_10069b10();
void BuildROIMap();
void UpdateStructMapAndROIIndex(LegoAnimStructMap& p_map, LegoTreeNode* p_node, LegoROI* p_roi);
void UpdateStructMapAndROIIndexForNode(
LegoAnimStructMap& p_map,
LegoAnimNodeData* p_data,
const LegoChar* p_und,
const LegoChar* p_key,
LegoROI* p_roi
);
void FUN_1006aa60();
void FUN_1006ab70();
LegoBool FUN_1006aba0();
MxBool FUN_1006abb0(LegoTreeNode* p_node, LegoROI* p_roi);
void ReleaseManagedActors();
void AppendManagedActors();
LegoBool VerifyAnimationTree();
MxBool VerifyAnimationNode(LegoTreeNode* p_node, LegoROI* p_roi);
void SubstituteVariables();
void FUN_1006b900(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix);
void FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix);
void ApplyTransform(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix);
void ApplyTransformWithVisibilityAndCam(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix);
void SetDisabled(MxBool p_disabled);
LegoAnim* m_anim; // 0x64
@ -133,27 +139,27 @@ class LegoAnimPresenter : public MxVideoPresenter {
MxU32 m_roiMapSize; // 0x6c
LegoROIList* m_sceneROIs; // 0x70
LegoROIList* m_managedActors; // 0x74
Matrix4* m_unk0x78; // 0x78
Matrix4* m_transform; // 0x78
MxU32 m_flags; // 0x7c
LegoWorld* m_currentWorld; // 0x80
MxAtomId m_worldAtom; // 0x84
MxS32 m_worldId; // 0x88
LegoROI** m_unk0x8c; // 0x8c
char** m_unk0x90; // 0x90
MxU8 m_unk0x94; // 0x94
MxBool m_unk0x95; // 0x95
MxBool m_unk0x96; // 0x96
LegoROI** m_ptAtCamROI; // 0x8c
char** m_ptAtCamNames; // 0x90
MxU8 m_ptAtCamCount; // 0x94
MxBool m_animationFinished; // 0x95
MxBool m_localActors; // 0x96
undefined m_unk0x97; // 0x97
LegoAnimSubstMap* m_substMap; // 0x98
MxS16 m_unk0x9c; // 0x9c
Matrix4* m_unk0xa0; // 0xa0
MxS16 m_roiTransformApplied; // 0x9c
Matrix4* m_roiTransform; // 0xa0
// SYNTHETIC: LEGO1 0x10068650
// LegoAnimPresenter::`scalar deleting destructor'
public:
float m_unk0xa4; // 0xa4
Mx3DPointFloat m_unk0xa8; // 0xa8
float m_boundingRadius; // 0xa4
Mx3DPointFloat m_centerPoint; // 0xa8
};
// VTABLE: LEGO1 0x100d4900
@ -231,16 +237,16 @@ class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter {
void PutFrame() override; // vtable+0x6c
MxResult CreateAnim(MxStreamChunk* p_chunk) override; // vtable+0x88
void FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value);
void CreateROIAndBuildMap(LegoAnimActor* p_actor, MxFloat p_worldSpeed);
void DecrementUnknown0xd4()
void DecrementWorldRefCounter()
{
if (m_unk0xd4) {
--m_unk0xd4;
if (m_worldRefCounter) {
--m_worldRefCounter;
}
}
undefined2 GetUnknown0xd4() { return m_unk0xd4; }
MxS16 GetWorldRefCounter() { return m_worldRefCounter; }
// SYNTHETIC: LEGO1 0x1006cfe0
// LegoLocomotionAnimPresenter::`scalar deleting destructor'
@ -254,7 +260,7 @@ class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter {
LegoROIMapList* m_roiMapList; // 0xc8
MxS32 m_unk0xcc; // 0xcc
MxS32 m_unk0xd0; // 0xd0
undefined2 m_unk0xd4; // 0xd4
MxS16 m_worldRefCounter; // 0xd4
};
class LegoPathBoundary;
@ -279,10 +285,10 @@ class LegoHideAnimPresenter : public LegoLoopingAnimPresenter {
~LegoHideAnimPresenter() override;
// FUNCTION: LEGO1 0x1006d860
void VTable0x8c() override {} // vtable+0x8c
void AddToWorld() override {} // vtable+0x8c
// FUNCTION: LEGO1 0x1006d870
void VTable0x90() override {} // vtable+0x90
void RemoveFromWorld() override {} // vtable+0x90
// FUNCTION: BETA10 0x1005d4a0
static const char* HandlerClassName()
@ -311,7 +317,7 @@ class LegoHideAnimPresenter : public LegoLoopingAnimPresenter {
void EndAction() override; // vtable+0x40
void PutFrame() override; // vtable+0x6c
void FUN_1006db40(LegoTime p_time);
void ApplyVisibility(LegoTime p_time);
// SYNTHETIC: LEGO1 0x1006d9d0
// LegoHideAnimPresenter::`scalar deleting destructor'
@ -319,10 +325,10 @@ class LegoHideAnimPresenter : public LegoLoopingAnimPresenter {
private:
void Init();
void Destroy(MxBool p_fromDestructor);
void FUN_1006db60(LegoTreeNode* p_node, LegoTime p_time);
void FUN_1006dc10();
void FUN_1006e3f0(LegoHideAnimStructMap& p_map, LegoTreeNode* p_node);
void FUN_1006e470(
void ApplyVisibility(LegoTreeNode* p_node, LegoTime p_time);
void AssignIndiciesWithMap();
void BuildMap(LegoHideAnimStructMap& p_map, LegoTreeNode* p_node);
void CheckedAdd(
LegoHideAnimStructMap& p_map,
LegoAnimNodeData* p_data,
const char* p_name,

View File

@ -43,8 +43,13 @@ class LegoEventNotificationParam : public MxNotificationParam {
{
}
// FUNCTION: BETA10 0x10026070
LegoROI* GetROI() { return m_roi; }
// FUNCTION: BETA10 0x1006aab0
MxU8 GetModifier() { return m_modifier; }
// FUNCTION: BETA10 0x100179a0
SDL_Keycode GetKey() const { return m_key; }
// FUNCTION: LEGO1 0x10012190

View File

@ -36,45 +36,52 @@ class LegoExtraActor : public virtual LegoAnimActor {
return !strcmp(p_name, LegoExtraActor::ClassName()) || LegoAnimActor::IsA(p_name);
}
void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30
MxS32 VTable0x68(Vector3& p_point1, Vector3& p_point2, Vector3& p_point3) override; // vtable+0x68
inline MxU32 VTable0x6c(
void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30
MxS32 CheckIntersections(Vector3& p_rayOrigin, Vector3& p_rayEnd, Vector3& p_intersectionPoint)
override; // vtable+0x68
inline MxU32 CheckPresenterAndActorIntersections(
LegoPathBoundary* p_boundary,
Vector3& p_v1,
Vector3& p_v2,
float p_f1,
float p_f2,
Vector3& p_v3
) override; // vtable+0x6c
void Animate(float p_time) override; // vtable+0x70
void VTable0x74(Matrix4& p_transform) override; // vtable+0x74
MxU32 VTable0x90(float p_time, Matrix4& p_matrix) override; // vtable+0x90
MxResult HitActor(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94
MxResult VTable0x9c() override; // vtable+0x9c
void VTable0xa4(MxBool& p_und1, MxS32& p_und2) override; // vtable+0xa4
void VTable0xc4() override; // vtable+0xc4
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint
) override; // vtable+0x6c
void Animate(float p_time) override; // vtable+0x70
void ApplyTransform(Matrix4& p_transform) override; // vtable+0x74
MxU32 StepState(float p_time, Matrix4& p_matrix) override; // vtable+0x90
MxResult HitActor(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94
MxResult CalculateSpline() override; // vtable+0x9c
void GetWalkingBehavior(MxBool& p_countCounterclockWise, MxS32& p_selectedEdgeIndex) override; // vtable+0xa4
void VTable0xc4() override; // vtable+0xc4
virtual MxResult FUN_1002aae0();
virtual MxResult SwitchDirection();
void Restart();
inline void FUN_1002ad8a();
inline void InitializeReassemblyAnim();
void SetUnknown0x0c(undefined p_unk0x0c) { m_unk0x0c = p_unk0x0c; }
void SetPathWalkingMode(MxU8 p_pathWalkingMode) { m_pathWalkingMode = p_pathWalkingMode; }
// SYNTHETIC: LEGO1 0x1002b760
// LegoExtraActor::`scalar deleting destructor'
private:
MxFloat m_scheduledTime; // 0x08
undefined m_unk0x0c; // 0x0c
MxU8 m_axis; // 0x0d
undefined m_unk0x0e; // 0x0e
MxFloat m_prevWorldSpeed; // 0x10
MxU8 m_whichAnim; // 0x14
MxU8 m_unk0x15; // 0x15
MxMatrix m_unk0x18; // 0x18
LegoAnimActorStruct* m_assAnim; // 0x60
LegoAnimActorStruct* m_disAnim; // 0x64
enum {
e_none = 0,
e_disassemble = 1,
e_assemble = 2,
};
MxFloat m_scheduledTime; // 0x08
MxU8 m_pathWalkingMode; // 0x0c
MxU8 m_axis; // 0x0d
MxBool m_animationAtCurrentBoundary; // 0x0e
MxFloat m_prevWorldSpeed; // 0x10
MxU8 m_reassemblyAnimation; // 0x14
MxU8 m_hitBlockCounter; // 0x15
MxMatrix m_localBeforeHit; // 0x18
LegoAnimActorStruct* m_assAnim; // 0x60
LegoAnimActorStruct* m_disAnim; // 0x64
};
// GLOBAL: LEGO1 0x100d6be8

View File

@ -44,7 +44,7 @@ class LegoNavController : public MxCore {
const Vector3& p_curDir,
Vector3& p_newPos,
Vector3& p_newDir,
const Vector3* p_und
const Vector3* p_up
);
static void GetDefaults(
@ -126,36 +126,36 @@ class LegoNavController : public MxCore {
float CalculateNewTargetVel(int p_pos, int p_center, float p_max);
float CalculateNewAccel(int p_pos, int p_center, float p_max, int p_min);
MxResult ProcessJoystickInput(MxBool& p_und);
MxResult ProcessJoystickInput(MxBool& p_rotatedY);
MxResult ProcessKeyboardInput();
int m_hMax; // 0x08
int m_vMax; // 0x0c
int m_deadZone; // 0x10
float m_zeroThreshold; // 0x14
float m_linearVel; // 0x18
float m_rotationalVel; // 0x1c
float m_targetLinearVel; // 0x20
float m_targetRotationalVel; // 0x24
float m_maxLinearVel; // 0x28
float m_maxRotationalVel; // 0x2c
float m_linearAccel; // 0x30
float m_rotationalAccel; // 0x34
float m_maxLinearAccel; // 0x38
float m_maxRotationalAccel; // 0x3c
float m_minLinearAccel; // 0x40
float m_minRotationalAccel; // 0x44
float m_maxLinearDeccel; // 0x48
float m_maxRotationalDeccel; // 0x4c
float m_rotSensitivity; // 0x50
MxBool m_useRotationalVel; // 0x54
MxTime m_lastTime; // 0x58
MxBool m_trackDefault; // 0x5c
MxBool m_unk0x5d; // 0x5d
float m_unk0x60; // 0x60
float m_unk0x64; // 0x64
float m_unk0x68; // 0x68
MxBool m_isAccelerating; // 0x6c
int m_hMax; // 0x08
int m_vMax; // 0x0c
int m_deadZone; // 0x10
float m_zeroThreshold; // 0x14
float m_linearVel; // 0x18
float m_rotationalVel; // 0x1c
float m_targetLinearVel; // 0x20
float m_targetRotationalVel; // 0x24
float m_maxLinearVel; // 0x28
float m_maxRotationalVel; // 0x2c
float m_linearAccel; // 0x30
float m_rotationalAccel; // 0x34
float m_maxLinearAccel; // 0x38
float m_maxRotationalAccel; // 0x3c
float m_minLinearAccel; // 0x40
float m_minRotationalAccel; // 0x44
float m_maxLinearDeccel; // 0x48
float m_maxRotationalDeccel; // 0x4c
float m_rotSensitivity; // 0x50
MxBool m_useRotationalVel; // 0x54
MxTime m_lastTime; // 0x58
MxBool m_trackDefault; // 0x5c
MxBool m_keyPressed; // 0x5d
float m_additionalHeightOffset; // 0x60
float m_additionalScale; // 0x64
float m_additionalRotationY; // 0x68
MxBool m_isAccelerating; // 0x6c
// one copy of defaults (these can be set by App.)
static int g_defdeadZone;

View File

@ -2,7 +2,7 @@
#define LEGOPATHACTOR_H
#include "legoactor.h"
#include "misc/legounknown.h"
#include "misc/legospline.h"
#include "mxtypes.h"
struct LegoEdge;
@ -24,9 +24,9 @@ class LegoPathActor : public LegoActor {
enum ActorState {
// States
c_initial = 0,
c_one = 1,
c_two = 2,
c_three = 3,
c_ready = 1,
c_hit = 2,
c_hitAnimation = 3,
c_disabled = 4,
c_maxState = 255,
@ -37,18 +37,22 @@ class LegoPathActor : public LegoActor {
LegoPathActor();
~LegoPathActor() override;
void ParseAction(char* p_extra) override; // vtable+0x20
virtual MxS32 VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3); // vtable+0x68
virtual MxU32 VTable0x6c(
void ParseAction(char* p_extra) override; // vtable+0x20
virtual MxS32 CheckIntersections(
Vector3& p_rayOrigin,
Vector3& p_rayEnd,
Vector3& p_intersectionPoint
); // vtable+0x68
virtual MxU32 CheckPresenterAndActorIntersections(
LegoPathBoundary* p_boundary,
Vector3& p_v1,
Vector3& p_v2,
float p_f1,
float p_f2,
Vector3& p_v3
); // vtable+0x6c
virtual void Animate(float p_time); // vtable+0x70
virtual void VTable0x74(Matrix4& p_transform); // vtable+0x74
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint
); // vtable+0x6c
virtual void Animate(float p_time); // vtable+0x70
virtual void ApplyTransform(Matrix4& p_transform); // vtable+0x74
// FUNCTION: LEGO1 0x10002d20
// FUNCTION: BETA10 0x1000f500
@ -58,33 +62,33 @@ class LegoPathActor : public LegoActor {
// FUNCTION: BETA10 0x1000f530
virtual MxBool GetUserNavFlag() { return m_userNavFlag; } // vtable+0x7c
virtual MxResult VTable0x80(
const Vector3& p_point1,
Vector3& p_point2,
Vector3& p_point3,
Vector3& p_point4
virtual MxResult SetSpline(
const Vector3& p_start,
Vector3& p_tangentAtStart,
Vector3& p_end,
Vector3& p_tangentAtEnd
); // vtable+0x80
virtual MxResult VTable0x84(
virtual MxResult SetTransformAndDestinationFromPoints(
LegoPathBoundary* p_boundary,
float p_time,
Vector3& p_p1,
Vector3& p_p4,
Vector3& p_start,
Vector3& p_direction,
LegoOrientedEdge* p_destEdge,
float p_destScale
); // vtable+0x84
virtual MxResult VTable0x88(
virtual MxResult SetTransformAndDestinationFromEdge(
LegoPathBoundary* p_boundary,
float p_time,
LegoEdge& p_srcEdge,
float p_srcScale,
LegoOrientedEdge& p_destEdge,
float p_destScale
); // vtable+0x88
virtual MxS32 VTable0x8c(float p_time, Matrix4& p_transform); // vtable+0x8c
); // vtable+0x88
virtual MxS32 CalculateTransform(float p_time, Matrix4& p_transform); // vtable+0x8c
// FUNCTION: LEGO1 0x10002d40
// FUNCTION: BETA10 0x1000f560
virtual MxU32 VTable0x90(float, Matrix4&) { return FALSE; } // vtable+0x90
virtual MxU32 StepState(float, Matrix4&) { return FALSE; } // vtable+0x90
// FUNCTION: LEGO1 0x10002d50
// FUNCTION: BETA10 0x1000f800
@ -93,16 +97,16 @@ class LegoPathActor : public LegoActor {
virtual void SwitchBoundary(
LegoPathBoundary*& p_boundary,
LegoOrientedEdge*& p_edge,
float& p_unk0xe4
); // vtable+0x98
virtual MxResult VTable0x9c(); // vtable+0x9c
float& p_scale
); // vtable+0x98
virtual MxResult CalculateSpline(); // vtable+0x9c
// FUNCTION: LEGO1 0x10002d60
// FUNCTION: BETA10 0x1000f820
virtual MxS32 NextTargetLocation() { return 0; } // vtable+0xa0
virtual void VTable0xa4(MxBool& p_und1, MxS32& p_und2); // vtable+0xa4
virtual void VTable0xa8(); // vtable+0xa8
virtual void GetWalkingBehavior(MxBool& p_countCounterclockWise, MxS32& p_selectedEdgeIndex); // vtable+0xa4
virtual void ApplyLocal2World(); // vtable+0xa8
// FUNCTION: LEGO1 0x10002d70
// FUNCTION: BETA10 0x1000f580
@ -114,26 +118,32 @@ class LegoPathActor : public LegoActor {
// FUNCTION: LEGO1 0x10002d90
// FUNCTION: BETA10 0x1000f5e0
virtual MxFloat VTable0xb4() { return m_unk0x140; } // vtable+0xb4
virtual MxFloat GetWallHitDirectionFactor() { return m_wallHitDirectionFactor; } // vtable+0xb4
// FUNCTION: LEGO1 0x10002da0
// FUNCTION: BETA10 0x1000f610
virtual MxFloat VTable0xb8() { return m_unk0x144; } // vtable+0xb8
virtual MxFloat GetWallHitDampening() { return m_wallHitDampening; } // vtable+0xb8
// FUNCTION: LEGO1 0x10002db0
// FUNCTION: BETA10 0x1000f640
virtual void VTable0xbc(MxFloat p_unk0x140) { m_unk0x140 = p_unk0x140; } // vtable+0xbc
virtual void SetWallHitDirectionFactor(MxFloat p_wallHitDirectionFactor)
{
m_wallHitDirectionFactor = p_wallHitDirectionFactor;
} // vtable+0xbc
// FUNCTION: LEGO1 0x10002dc0
// FUNCTION: BETA10 0x1000f670
virtual void VTable0xc0(MxFloat p_unk0x144) { m_unk0x144 = p_unk0x144; } // vtable+0xc0
virtual void SetWallHitDampening(MxFloat p_wallHitDampening)
{
m_wallHitDampening = p_wallHitDampening;
} // vtable+0xc0
// FUNCTION: LEGO1 0x10002dd0
// FUNCTION: BETA10 0x1000f6a0
virtual void VTable0xc4() {} // vtable+0xc4
// FUNCTION: LEGO1 0x10002de0
virtual void VTable0xc8(MxU8 p_unk0x148) { m_unk0x148 = p_unk0x148; } // vtable+0xc8
virtual void SetCanRotate(MxU8 p_canRotate) { m_canRotate = p_canRotate; } // vtable+0xc8
// FUNCTION: LEGO1 0x1000c430
// FUNCTION: BETA10 0x10012790
@ -158,7 +168,7 @@ class LegoPathActor : public LegoActor {
LegoPathController* GetController() { return m_pathController; }
MxBool GetCollideBox() { return m_collideBox; }
MxFloat GetLastTime() { return m_lastTime; }
MxFloat GetTransformTime() { return m_transformTime; }
MxFloat GetActorTime() { return m_actorTime; }
void SetBoundary(LegoPathBoundary* p_boundary) { m_boundary = p_boundary; }
@ -167,7 +177,7 @@ class LegoPathActor : public LegoActor {
void SetActorState(MxU32 p_actorState) { m_actorState = p_actorState; }
void SetController(LegoPathController* p_pathController) { m_pathController = p_pathController; }
void SetLastTime(MxFloat p_lastTime) { m_lastTime = p_lastTime; }
void SetTransformTime(MxFloat p_transformTime) { m_transformTime = p_transformTime; }
void SetActorTime(MxFloat p_actorTime) { m_actorTime = p_actorTime; }
void UpdatePlane(LegoNamedPlane& p_namedPlane);
@ -178,42 +188,42 @@ class LegoPathActor : public LegoActor {
// LegoPathActor::`scalar deleting destructor'
protected:
inline MxU32 FUN_1002edd0(
list<LegoPathBoundary*>& p_boundaries,
inline MxU32 CheckIntersectionBothFaces(
list<LegoPathBoundary*>& p_checkedBoundaries,
LegoPathBoundary* p_boundary,
Vector3& p_v1,
Vector3& p_v2,
float p_f1,
float p_f2,
Vector3& p_v3,
MxS32 p_und
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint,
MxS32 p_depth
);
MxFloat m_BADuration; // 0x78
MxFloat m_unk0x7c; // 0x7c
MxFloat m_traveledDistance; // 0x7c
MxFloat m_actorTime; // 0x80
MxFloat m_lastTime; // 0x84
MxFloat m_transformTime; // 0x84
LegoPathBoundary* m_boundary; // 0x88
LegoUnknown m_unk0x8c; // 0x8c
LegoSpline m_spline; // 0x8c
MxU32 m_actorState; // 0xdc
LegoOrientedEdge* m_destEdge; // 0xe0
MxFloat m_unk0xe4; // 0xe4
MxFloat m_destScale; // 0xe4
MxBool m_collideBox; // 0xe8
MxBool m_unk0xe9; // 0xe9
MxBool m_finishedTravel; // 0xe9
MxBool m_userNavFlag; // 0xea
MxMatrix m_unk0xec; // 0xec
MxMatrix m_local2World; // 0xec
LegoPathEdgeContainer* m_grec; // 0x134
LegoPathController* m_pathController; // 0x138
MxFloat m_maxLinearVel; // 0x13c
MxFloat m_unk0x140; // 0x140
MxFloat m_unk0x144; // 0x144
MxU8 m_unk0x148; // 0x148
MxS32 m_unk0x14c; // 0x14c
MxFloat m_unk0x150; // 0x150
MxFloat m_wallHitDirectionFactor; // 0x140
MxFloat m_wallHitDampening; // 0x144
MxU8 m_canRotate; // 0x148
MxS32 m_lastRotationAngle; // 0x14c
MxFloat m_linearRotationRatio; // 0x150
};
// FUNCTION: LEGO1 0x1002edd0
// LegoPathActor::FUN_1002edd0
// LegoPathActor::CheckIntersectionBothFaces
// TEMPLATE: LEGO1 0x10018b70
// List<LegoBoundaryEdge>::~List<LegoBoundaryEdge>

View File

@ -40,14 +40,20 @@ class LegoPathBoundary : public LegoWEGEdge {
MxResult AddActor(LegoPathActor* p_actor);
MxResult RemoveActor(LegoPathActor* p_actor);
void CheckAndCallPathTriggers(Vector3& p_point1, Vector3& p_point2, LegoPathActor* p_actor);
void CheckAndCallPathTriggers(Vector3& p_from, Vector3& p_to, LegoPathActor* p_actor);
void SwitchBoundary(
LegoPathActor* p_actor,
LegoPathBoundary*& p_boundary,
LegoOrientedEdge*& p_edge,
float& p_unk0xe4
float& p_scale
);
MxU32 Intersect(
float p_scale,
Vector3& p_oldPos,
Vector3& p_newPos,
Vector3& p_intersectionPoint,
LegoOrientedEdge*& p_edge
);
MxU32 Intersect(float p_scale, Vector3& p_point1, Vector3& p_point2, Vector3& p_point3, LegoOrientedEdge*& p_edge);
MxU32 AddPresenterIfInRange(LegoAnimPresenter* p_presenter);
MxU32 RemovePresenter(LegoAnimPresenter* p_presenter);

View File

@ -109,13 +109,13 @@ class LegoPathController : public MxCore {
);
MxResult PlaceActor(LegoPathActor* p_actor);
MxResult RemoveActor(LegoPathActor* p_actor);
void FUN_100468f0(LegoAnimPresenter* p_presenter);
void AddPresenterIfInRange(LegoAnimPresenter* p_presenter);
void RemovePresenterFromBoundaries(LegoAnimPresenter* p_presenter);
MxResult FUN_10046b30(LegoPathBoundary*& p_boundaries, MxS32& p_numL);
MxResult GetBoundaries(LegoPathBoundary*& p_boundaries, MxS32& p_numL);
LegoPathBoundary* GetPathBoundary(const char* p_name);
void Enable(MxBool p_enable);
void FUN_10046bb0(LegoWorld* p_world);
MxResult FUN_10048310(
void SetWorld(LegoWorld* p_world);
MxResult FindPath(
LegoPathEdgeContainer* p_grec,
const Vector3& p_oldPosition,
const Vector3& p_oldDirection,
@ -124,17 +124,17 @@ class LegoPathController : public MxCore {
const Vector3& p_newDirection,
LegoPathBoundary* p_newBoundary,
LegoU8 p_mask,
MxFloat* p_param9
MxFloat* p_distance
);
MxS32 FUN_1004a240(
MxS32 GetNextPathEdge(
LegoPathEdgeContainer& p_grec,
Vector3& p_v1,
Vector3& p_v2,
Vector3& p_position,
Vector3& p_direction,
float p_f1,
LegoOrientedEdge*& p_edge,
LegoPathBoundary*& p_boundary
);
MxResult FUN_1004a380(
MxResult FindIntersectionBoundary(
Vector3& p_param1,
Vector3& p_param2,
Mx3DPointFloat* p_param3,
@ -159,7 +159,7 @@ class LegoPathController : public MxCore {
static LegoPathBoundary* GetControlBoundaryB(MxS32 p_index) { return g_ctrlBoundariesB[p_index].m_boundary; }
private:
void FUN_10046970();
void AnimateActors();
MxResult Read(LegoStorage* p_storage);
MxResult ReadStructs(LegoStorage* p_storage);
MxResult ReadEdges(LegoStorage* p_storage);
@ -179,7 +179,7 @@ class LegoPathController : public MxCore {
}
// FUNCTION: BETA10 0x100c17a0
static MxU32 FUN_100c17a0(MxFloat p_v1, MxFloat p_v2, MxFloat p_a, MxFloat p_b)
static MxU32 BothSameComparison(MxFloat p_v1, MxFloat p_v2, MxFloat p_a, MxFloat p_b)
{
assert(IsBetween(p_v1, p_a, p_b));
assert(IsBetween(p_v2, p_a, p_b));
@ -207,8 +207,8 @@ class LegoPathController : public MxCore {
static CtrlBoundary* g_ctrlBoundariesA;
static CtrlEdge* g_ctrlEdgesA;
static const char* g_unk0x100f42f0[];
static const char* g_unk0x100f4330[];
static const char* g_ctrlBoundariesNamesA[];
static const char* g_ctrlBoundariesNamesB[];
static CtrlBoundary* g_ctrlBoundariesB;
static CtrlEdge* g_ctrlEdgesB;
};
@ -296,58 +296,58 @@ class LegoPathController : public MxCore {
// _Tree<LegoPathCtrlEdge *,LegoPathCtrlEdge *,set<LegoPathCtrlEdge *,LegoPathCtrlEdgeCompare,allocator<LegoPathCtrlEdge *> >::_Kfn,LegoPathCtrlEdgeCompare,allocator<LegoPathCtrlEdge *> >::_Ubound
// TEMPLATE: LEGO1 0x100493a0
// list<LegoBEWithFloat,allocator<LegoBEWithFloat> >::~list<LegoBEWithFloat,allocator<LegoBEWithFloat> >
// list<LegoBEWithMidpoint,allocator<LegoBEWithMidpoint> >::~list<LegoBEWithMidpoint,allocator<LegoBEWithMidpoint> >
// TEMPLATE: LEGO1 0x10049410
// list<LegoBEWithFloat,allocator<LegoBEWithFloat> >::insert
// list<LegoBEWithMidpoint,allocator<LegoBEWithMidpoint> >::insert
// TEMPLATE: LEGO1 0x10049470
// list<LegoBEWithFloat,allocator<LegoBEWithFloat> >::_Buynode
// list<LegoBEWithMidpoint,allocator<LegoBEWithMidpoint> >::_Buynode
// TEMPLATE: LEGO1 0x100494a0
// _Tree<LegoBEWithFloat *,LegoBEWithFloat *,multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Kfn,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::iterator::_Inc
// _Tree<LegoBEWithMidpoint *,LegoBEWithMidpoint *,multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Kfn,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::iterator::_Inc
// TEMPLATE: LEGO1 0x100494e0
// _Tree<LegoBEWithFloat *,LegoBEWithFloat *,multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Kfn,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::~_Tree<LegoBEWithFloat *,LegoBEWithFloat *,multiset<LegoBEWithFlo
// _Tree<LegoBEWithMidpoint *,LegoBEWithMidpoint *,multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Kfn,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::~_Tree<LegoBEWithMidpoint *,LegoBEWithMidpoint *,multiset<LegoBEWithFlo
// TEMPLATE: LEGO1 0x100495b0
// _Tree<LegoBEWithFloat *,LegoBEWithFloat *,multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Kfn,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::insert
// _Tree<LegoBEWithMidpoint *,LegoBEWithMidpoint *,multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Kfn,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::insert
// TEMPLATE: LEGO1 0x10049840
// _Tree<LegoBEWithFloat *,LegoBEWithFloat *,multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Kfn,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::iterator::_Dec
// _Tree<LegoBEWithMidpoint *,LegoBEWithMidpoint *,multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Kfn,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::iterator::_Dec
// TEMPLATE: LEGO1 0x10049890
// _Tree<LegoBEWithFloat *,LegoBEWithFloat *,multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Kfn,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::erase
// _Tree<LegoBEWithMidpoint *,LegoBEWithMidpoint *,multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Kfn,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::erase
// TEMPLATE: LEGO1 0x10049cf0
// _Tree<LegoBEWithFloat *,LegoBEWithFloat *,multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Kfn,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Buynode
// _Tree<LegoBEWithMidpoint *,LegoBEWithMidpoint *,multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Kfn,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Buynode
// TEMPLATE: LEGO1 0x10049d50
// _Tree<LegoBEWithFloat *,LegoBEWithFloat *,multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Kfn,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Init
// _Tree<LegoBEWithMidpoint *,LegoBEWithMidpoint *,multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Kfn,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Init
// TEMPLATE: LEGO1 0x10049e00
// _Tree<LegoBEWithFloat *,LegoBEWithFloat *,multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Kfn,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Insert
// _Tree<LegoBEWithMidpoint *,LegoBEWithMidpoint *,multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Kfn,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Insert
// TEMPLATE: LEGO1 0x10049d10
// _Tree<LegoBEWithFloat *,LegoBEWithFloat *,multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Kfn,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Erase
// _Tree<LegoBEWithMidpoint *,LegoBEWithMidpoint *,multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Kfn,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Erase
// TEMPLATE: LEGO1 0x1004a090
// _Tree<LegoBEWithFloat *,LegoBEWithFloat *,multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Kfn,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Lrotate
// _Tree<LegoBEWithMidpoint *,LegoBEWithMidpoint *,multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Kfn,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Lrotate
// TEMPLATE: LEGO1 0x1004a0f0
// _Tree<LegoBEWithFloat *,LegoBEWithFloat *,multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Kfn,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Rrotate
// _Tree<LegoBEWithMidpoint *,LegoBEWithMidpoint *,multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Kfn,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Rrotate
// TEMPLATE: LEGO1 0x1004a150
// List<LegoBEWithFloat>::~List<LegoBEWithFloat>
// List<LegoBEWithMidpoint>::~List<LegoBEWithMidpoint>
// TEMPLATE: LEGO1 0x1004a1a0
// Multiset<LegoBEWithFloat *,LegoBEWithFloatComparator>::~Multiset<LegoBEWithFloat *,LegoBEWithFloatComparator>
// Multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator>::~Multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator>
// TEMPLATE: LEGO1 0x1004a1f0
// multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::~multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >
// multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::~multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >
// TEMPLATE: LEGO1 0x1004a760
// ?_Construct@@YAXPAPAULegoBEWithFloat@@ABQAU1@@Z
// ?_Construct@@YAXPAPAULegoBEWithMidpoint@@ABQAU1@@Z
// TEMPLATE: LEGO1 0x1004a780
// ?_Construct@@YAXPAPAULegoPathCtrlEdge@@ABQAU1@@Z
@ -356,7 +356,7 @@ class LegoPathController : public MxCore {
// _Tree<LegoPathCtrlEdge *,LegoPathCtrlEdge *,set<LegoPathCtrlEdge *,LegoPathCtrlEdgeCompare,allocator<LegoPathCtrlEdge *> >::_Kfn,LegoPathCtrlEdgeCompare,allocator<LegoPathCtrlEdge *> >::_Nil
// GLOBAL: LEGO1 0x100f4364
// _Tree<LegoBEWithFloat *,LegoBEWithFloat *,multiset<LegoBEWithFloat *,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Kfn,LegoBEWithFloatComparator,allocator<LegoBEWithFloat *> >::_Nil
// _Tree<LegoBEWithMidpoint *,LegoBEWithMidpoint *,multiset<LegoBEWithMidpoint *,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Kfn,LegoBEWithMidpointComparator,allocator<LegoBEWithMidpoint *> >::_Nil
// clang-format on
#endif // LEGOPATHCONTROLLER_H

View File

@ -27,56 +27,61 @@ struct LegoBoundaryEdge {
};
// SIZE 0x10
struct LegoBEWithFloat {
LegoBEWithFloat()
struct LegoBEWithMidpoint {
LegoBEWithMidpoint()
{
m_edge = NULL;
m_boundary = NULL;
m_next = NULL;
m_unk0x0c = 0.0f;
m_distanceToMidpoint = 0.0f;
}
// FUNCTION: BETA10 0x100bd9a0
LegoBEWithFloat(LegoPathCtrlEdge* p_edge, LegoPathBoundary* p_boundary, MxFloat p_unk0x0c)
LegoBEWithMidpoint(LegoPathCtrlEdge* p_edge, LegoPathBoundary* p_boundary, MxFloat p_distanceToMidpoint)
{
m_edge = p_edge;
m_boundary = p_boundary;
m_next = NULL;
m_unk0x0c = p_unk0x0c;
m_distanceToMidpoint = p_distanceToMidpoint;
}
// FUNCTION: BETA10 0x100bd9f0
LegoBEWithFloat(LegoPathCtrlEdge* p_edge, LegoPathBoundary* p_boundary, LegoBEWithFloat* p_next, MxFloat p_unk0x0c)
LegoBEWithMidpoint(
LegoPathCtrlEdge* p_edge,
LegoPathBoundary* p_boundary,
LegoBEWithMidpoint* p_next,
MxFloat p_distanceToMidpoint
)
{
m_edge = p_edge;
m_boundary = p_boundary;
m_next = p_next;
m_unk0x0c = p_unk0x0c;
m_distanceToMidpoint = p_distanceToMidpoint;
}
LegoPathCtrlEdge* m_edge; // 0x00
LegoPathBoundary* m_boundary; // 0x04
LegoBEWithFloat* m_next; // 0x08
MxFloat m_unk0x0c; // 0x0c
LegoBEWithMidpoint* m_next; // 0x08
MxFloat m_distanceToMidpoint; // 0x0c
int operator==(LegoBEWithFloat) const { return 0; }
int operator<(LegoBEWithFloat) const { return 0; }
int operator==(LegoBEWithMidpoint) const { return 0; }
int operator<(LegoBEWithMidpoint) const { return 0; }
};
struct LegoBEWithFloatComparator {
struct LegoBEWithMidpointComparator {
// FUNCTION: BETA10 0x100bef80
bool operator()(LegoBEWithFloat* const& p_a, LegoBEWithFloat* const& p_b) const
bool operator()(LegoBEWithMidpoint* const& p_a, LegoBEWithMidpoint* const& p_b) const
{
return p_a->m_unk0x0c < p_b->m_unk0x0c;
return p_a->m_distanceToMidpoint < p_b->m_distanceToMidpoint;
}
};
typedef multiset<LegoBEWithFloat*, LegoBEWithFloatComparator> LegoBEWithFloatSet;
typedef multiset<LegoBEWithMidpoint*, LegoBEWithMidpointComparator> LegoBEWithMidpointSet;
// SIZE 0x3c
struct LegoPathEdgeContainer : public list<LegoBoundaryEdge> {
enum {
c_bit1 = 0x01
c_hasPath = 0x01
};
// FUNCTION: BETA10 0x100118e0
@ -87,18 +92,18 @@ struct LegoPathEdgeContainer : public list<LegoBoundaryEdge> {
}
// FUNCTION: BETA10 0x100bd660
void SetBit1(MxU32 p_set)
void SetPath(MxU32 p_set)
{
if (p_set) {
m_flags |= c_bit1;
m_flags |= c_hasPath;
}
else {
m_flags &= ~c_bit1;
m_flags &= ~c_hasPath;
}
}
// FUNCTION: BETA10 0x1001cb50
MxU32 GetBit1() { return m_flags & c_bit1; }
MxU32 HasPath() { return m_flags & c_hasPath; }
Mx3DPointFloat m_position; // 0x0c
Mx3DPointFloat m_direction; // 0x20

View File

@ -30,9 +30,13 @@ class LegoRaceActor : public virtual LegoAnimActor {
return !strcmp(p_name, LegoRaceActor::ClassName()) || LegoAnimActor::IsA(p_name);
}
MxS32 VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3) override; // vtable+0x68
MxU32 VTable0x90(float p_time, Matrix4& p_matrix) override; // vtable+0x90
MxResult HitActor(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94
MxS32 CheckIntersections(
Vector3& p_rayOrigin,
Vector3& p_rayEnd,
Vector3& p_intersectionPoint
) override; // vtable+0x68
MxU32 StepState(float p_time, Matrix4& p_matrix) override; // vtable+0x90
MxResult HitActor(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94
virtual MxResult FUN_10014aa0();

View File

@ -26,7 +26,7 @@ class LegoRaceMap : public virtual LegoRaceActor {
void Animate(float p_time) override = 0; // vtable+0x70
// LegoRaceMap vtable
virtual void FUN_1005d4b0(); // vtable+0x00
virtual void UpdateMapLocatorPosition(); // vtable+0x00
// SYNTHETIC: LEGO1 0x10012c50
// LegoRaceMap::`vbase destructor'
@ -35,28 +35,28 @@ class LegoRaceMap : public virtual LegoRaceActor {
// LegoRaceMap::`scalar deleting destructor'
private:
MxBool m_unk0x08; // 0x08
MxBool m_mapEnabled; // 0x08
MxStillPresenter* m_stillPresenter; // 0x0c
// variable name verified by BETA10 0x100ca82b
MxControlPresenter* m_Map_Ctl; // 0x10
// likely an x-offset of the race map in world space
float m_unk0x14; // 0x14
float m_worldXOffset; // 0x14
// inversely scales the map in x direction (either convert world->screen space or to control the size)
float m_unk0x18; // 0x18
// likely a y-offset of the race map in world space
float m_unk0x1c; // 0x1c
// inversely scales the map in y direction (either convert world->screen space or to control the size)
float m_unk0x20; // 0x20
float m_worldXScale; // 0x18
// likely a z-offset of the race map in world space
float m_worldZOffset; // 0x1c
// inversely scales the map in z direction (either convert world->screen space or to control the size)
float m_worldZScale; // 0x20
// scales the map in x direction (either convert world->screen space or to change the size)
float m_unk0x24; // 0x24
float m_screenXScale; // 0x24
// scales the map in y direction (either convert world->screen space or to change the size)
float m_unk0x28; // 0x28
float m_screenYScale; // 0x28
// likely an x-offset of the race map in screen space
float m_unk0x2c; // 0x2c
float m_screenXOffset; // 0x2c
// likely a y-offset of the race map in screen space
float m_unk0x30; // 0x30
float m_screenYOffset; // 0x30
};
// GLOBAL: LEGO1 0x100d8848

View File

@ -6,9 +6,11 @@
// clang-format on
#include "legoracemap.h"
#define LEGORACECAR_UNKNOWN_0 0
#define LEGORACECAR_UNKNOWN_1 1
#define LEGORACECAR_NONE 0
#define LEGORACECAR_NEAR_SKELETON 1
// kick to the left
#define LEGORACECAR_KICK1 2 // name guessed
// kick to the right
#define LEGORACECAR_KICK2 4 // name validated by BETA10 0x100cb659
// SIZE 0x08
@ -23,7 +25,7 @@ struct SkeletonKickPhase {
EdgeReference* m_edgeRef; // 0x00
float m_lower; // 0x04
float m_upper; // 0x08
MxU8 m_userState; // 0x0c
MxU8 m_kickState; // 0x0c
};
// VTABLE: LEGO1 0x100d5a08 LegoCarRaceActor
@ -62,10 +64,23 @@ class LegoJetski : public LegoJetskiRaceActor, public LegoRaceMap {
void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30
// FUNCTION: LEGO1 0x10014150
MxU32 VTable0x6c(LegoPathBoundary* p_boundary, Vector3& p_v1, Vector3& p_v2, float p_f1, float p_f2, Vector3& p_v3)
override
MxU32 CheckPresenterAndActorIntersections(
LegoPathBoundary* p_boundary,
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint
) override
{
return LegoJetskiRaceActor::VTable0x6c(p_boundary, p_v1, p_v2, p_f1, p_f2, p_v3);
return LegoJetskiRaceActor::CheckPresenterAndActorIntersections(
p_boundary,
p_rayOrigin,
p_rayDirection,
p_rayLength,
p_radius,
p_intersectionPoint
);
} // vtable+0x6c
void Animate(float p_time) override; // vtable+0x70
@ -78,9 +93,9 @@ class LegoJetski : public LegoJetskiRaceActor, public LegoRaceMap {
} // vtable+0x98
// FUNCTION: LEGO1 0x10014210
MxResult VTable0x9c() override { return LegoJetskiRaceActor::VTable0x9c(); } // vtable+0x9c
MxResult CalculateSpline() override { return LegoJetskiRaceActor::CalculateSpline(); } // vtable+0x9c
virtual void FUN_100136f0(float p_worldSpeed);
virtual void SetMaxLinearVelocity(float p_worldSpeed);
static void InitSoundIndices();
@ -125,10 +140,23 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap {
// FUNCTION: LEGO1 0x10014500
// FUNCTION: BETA10 0x100cd5e0
MxU32 VTable0x6c(LegoPathBoundary* p_boundary, Vector3& p_v1, Vector3& p_v2, float p_f1, float p_f2, Vector3& p_v3)
override
MxU32 CheckPresenterAndActorIntersections(
LegoPathBoundary* p_boundary,
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint
) override
{
return LegoCarRaceActor::VTable0x6c(p_boundary, p_v1, p_v2, p_f1, p_f2, p_v3);
return LegoCarRaceActor::CheckPresenterAndActorIntersections(
p_boundary,
p_rayOrigin,
p_rayDirection,
p_rayLength,
p_radius,
p_intersectionPoint
);
} // vtable+0x6c
void Animate(float p_time) override; // vtable+0x70
@ -141,7 +169,7 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap {
LegoCarRaceActor::SwitchBoundary(p_boundary, p_edge, p_unk0xe4);
} // vtable+0x98
MxResult VTable0x9c() override; // vtable+0x9c
MxResult CalculateSpline() override; // vtable+0x9c
virtual void SetMaxLinearVelocity(float p_maxLinearVelocity);
virtual void KickCamera(float p_param);
@ -154,7 +182,7 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap {
// LegoRaceCar::`scalar deleting destructor'
private:
undefined m_userState; // 0x54
MxU8 m_kickState; // 0x54
float m_kickStart; // 0x58
Mx3DPointFloat m_unk0x5c; // 0x5c

View File

@ -35,21 +35,21 @@ class LegoCarRaceActor : public virtual LegoRaceActor {
return !strcmp(p_name, LegoCarRaceActor::ClassName()) || LegoRaceActor::IsA(p_name);
}
MxU32 VTable0x6c(
MxU32 CheckPresenterAndActorIntersections(
LegoPathBoundary* p_boundary,
Vector3& p_v1,
Vector3& p_v2,
float p_f1,
float p_f2,
Vector3& p_v3
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint
) override; // vtable+0x6c
void Animate(float p_time) override; // vtable+0x70
void SwitchBoundary(
LegoPathBoundary*& p_boundary,
LegoOrientedEdge*& p_edge,
float& p_unk0xe4
) override; // vtable+0x98
MxResult VTable0x9c() override; // vtable+0x9c
) override; // vtable+0x98
MxResult CalculateSpline() override; // vtable+0x9c
// LegoCarRaceActor vtable
@ -130,13 +130,13 @@ class LegoJetskiRaceActor : public virtual LegoCarRaceActor {
return !strcmp(p_name, LegoJetskiRaceActor::ClassName()) || LegoCarRaceActor::IsA(p_name);
}
MxU32 VTable0x6c(
MxU32 CheckPresenterAndActorIntersections(
LegoPathBoundary* p_boundary,
Vector3& p_v1,
Vector3& p_v2,
float p_f1,
float p_f2,
Vector3& p_v3
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint
) override; // vtable+0x6c
void Animate(float p_time) override; // vtable+0x70
MxS32 VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edge) override; // vtable+0x1c

View File

@ -0,0 +1,44 @@
#ifndef LEGOTESTTIMER_H
#define LEGOTESTTIMER_H
#include "decomp.h"
#include "misc/legotypes.h"
#include "mxcore.h"
#include "mxparam.h"
// VTABLE: BETA10 0x101bed08
// SIZE 0x24
class LegoTestTimer : public MxCore {
public:
LegoTestTimer(LegoS32 p_numTimers, LegoS32 p_interval, LegoS32 p_numBins, LegoS32 p_type);
~LegoTestTimer() override; // vtable+00
MxLong Notify(MxParam& p_param) override; // vtable+04
// FUNCTION: BETA10 0x100d18e0
static const char* HandlerClassName() { return "LegoTestTimer"; }
// FUNCTION: BETA10 0x100d18b0
const char* ClassName() const override // vtable+0c
{
return HandlerClassName();
}
void Tick(LegoS32 p_timer);
void ResetAtNextTick();
void Print();
// SYNTHETIC: BETA10 0x100d1900
// LegoTestTimer::`scalar deleting destructor'
private:
LegoS32** m_timers; // 0x08
LegoS32* m_lastTime; // 0x0c
LegoS32* m_totalTime; // 0x10
LegoS32 m_numTimers; // 0x14
LegoS32 m_numBins; // 0x18
LegoS32 m_interval; // 0x1c
MxBool m_enable; // 0x20
MxBool m_keyRegistered; // 0x21
};
#endif // LEGOTESTTIMER_H

View File

@ -43,7 +43,7 @@ class LegoWorldPresenter : public LegoEntityPresenter {
void StartingTickle() override; // vtable+0x1c
void ParseExtra() override; // vtable+0x30
MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c
void VTable0x60(MxPresenter* p_presenter) override; // vtable+0x60
void AdvanceSerialAction(MxPresenter* p_presenter) override; // vtable+0x60
MxResult LoadWorld(char* p_worldName, LegoWorld* p_world);

View File

@ -32,8 +32,8 @@ class MxCompositeMediaPresenter : public MxCompositePresenter {
MxResult PutData() override; // vtable+0x4c
private:
MxS16 m_unk0x4c; // 0x4c
MxBool m_unk0x4e; // 0x4e
MxS16 m_remainingChildren; // 0x4c
MxBool m_allChildrenStreaming; // 0x4e
};
// SYNTHETIC: LEGO1 0x10074000

View File

@ -18,7 +18,7 @@ class MxControlPresenter : public MxCompositePresenter {
void RepeatingTickle() override {} // vtable+0x24
// FUNCTION: LEGO1 0x10043fe0
MxBool VTable0x64(undefined4 p_undefined) override { return m_unk0x50; } // vtable+0x64
MxBool GetActionEnded(undefined4 p_undefined) override { return m_unk0x50; } // vtable+0x64
// FUNCTION: LEGO1 0x10043ff0
virtual void VTable0x68(MxBool p_unk0x50) { m_unk0x50 = p_unk0x50; } // vtable+0x68

View File

@ -179,9 +179,9 @@ MxResult Act2Actor::HitActor(LegoPathActor*, MxBool)
}
// FUNCTION: LEGO1 0x10018a20
MxResult Act2Actor::VTable0x9c()
MxResult Act2Actor::CalculateSpline()
{
if (m_grec && !m_grec->GetBit1()) {
if (m_grec && !m_grec->HasPath()) {
delete m_grec;
m_grec = NULL;
return SUCCESS;
@ -198,7 +198,7 @@ MxResult Act2Actor::VTable0x9c()
brickstrROI->UpdateTransformationRelativeToParent(brickstrMatrix);
}
return LegoPathActor::VTable0x9c();
return LegoPathActor::CalculateSpline();
}
}
@ -410,7 +410,7 @@ void Act2Actor::FindPath(MxU32 p_location)
newDirection = g_brickstrLocations[p_location].m_direction;
LegoPathBoundary* newBoundary = m_pathController->GetPathBoundary(g_brickstrLocations[p_location].m_boundary);
MxResult sts = m_pathController->FUN_10048310(
MxResult sts = m_pathController->FindPath(
m_grec,
m_roi->GetWorldPosition(),
m_roi->GetWorldDirection(),
@ -607,7 +607,7 @@ MxU32 Act2Actor::UpdateShot(MxFloat p_time)
return FALSE;
}
m_lastTime = p_time;
m_transformTime = p_time;
LegoROI* brickstrROI = FindROI("brickstr");
MxMatrix initialTransform = m_roi->GetLocal2World();

View File

@ -101,20 +101,20 @@ Act3Actor::Act3Actor()
// FUNCTION: LEGO1 0x1003fb70
// FUNCTION: BETA10 0x100180ab
MxU32 Act3Actor::VTable0x90(float p_time, Matrix4& p_transform)
MxU32 Act3Actor::StepState(float p_time, Matrix4& p_transform)
{
// Note: Code duplication with LegoExtraActor::VTable0x90
// Note: Code duplication with LegoExtraActor::StepState
switch (m_actorState & c_maxState) {
case c_initial:
case c_one:
case c_ready:
return TRUE;
case c_two:
case c_hit:
m_unk0x1c = p_time + 2000.0f;
m_actorState = c_three;
m_actorTime += (p_time - m_lastTime) * m_worldSpeed;
m_lastTime = p_time;
m_actorState = c_hitAnimation;
m_actorTime += (p_time - m_transformTime) * m_worldSpeed;
m_transformTime = p_time;
return FALSE;
case c_three:
case c_hitAnimation:
assert(!m_userNavFlag);
Vector3 positionRef(p_transform[3]);
@ -128,10 +128,10 @@ MxU32 Act3Actor::VTable0x90(float p_time, Matrix4& p_transform)
p_transform.RotateX(0.6);
positionRef = position;
m_actorTime += (p_time - m_lastTime) * m_worldSpeed;
m_lastTime = p_time;
m_actorTime += (p_time - m_transformTime) * m_worldSpeed;
m_transformTime = p_time;
VTable0x74(p_transform);
ApplyTransform(p_transform);
return FALSE;
}
else {
@ -167,7 +167,7 @@ MxResult Act3Actor::HitActor(LegoPathActor* p_actor, MxBool p_bool)
roi->SetLocal2World(local2world);
roi->WrappedUpdateWorldData();
p_actor->SetActorState(c_two | c_noCollide);
p_actor->SetActorState(c_hit | c_noCollide);
}
return SUCCESS;
@ -196,7 +196,7 @@ MxResult Act3Cop::HitActor(LegoPathActor* p_actor, MxBool p_bool)
assert(m_world);
((Act3*) m_world)->EatDonut(index);
m_unk0x20 = m_lastTime + 2000;
m_unk0x20 = m_transformTime + 2000;
SetWorldSpeed(6.0);
assert(SoundManager()->GetCacheSoundManager());
@ -285,7 +285,7 @@ void Act3Cop::Animate(float p_time)
{
Act3Actor::Animate(p_time);
if (m_unk0x20 > 0.0f && m_unk0x20 < m_lastTime) {
if (m_unk0x20 > 0.0f && m_unk0x20 < m_transformTime) {
SetWorldSpeed(2.0f);
m_unk0x20 = -1.0f;
}
@ -329,7 +329,7 @@ MxResult Act3Cop::FUN_10040360()
LegoPathEdgeContainer* grec = NULL;
Act3* a3 = (Act3*) m_world;
MxMatrix local74(m_unk0xec);
MxMatrix local74(m_local2World);
Vector3 local2c(local74[3]);
Vector3 local20(local74[2]);
@ -346,7 +346,7 @@ MxResult Act3Cop::FUN_10040360()
assert(grec);
MxFloat local34;
if (m_pathController->FUN_10048310(
if (m_pathController->FindPath(
grec,
local2c,
local20,
@ -384,7 +384,7 @@ MxResult Act3Cop::FUN_10040360()
MxFloat locald8;
LegoPathEdgeContainer *local138, *local134, *local140, *local13c; // unused
if (m_pathController->FUN_10048310(
if (m_pathController->FindPath(
r2,
local2c,
local20,
@ -424,7 +424,7 @@ MxResult Act3Cop::FUN_10040360()
MxFloat local100;
LegoPathEdgeContainer *local150, *local14c; // unused
if (m_pathController->FUN_10048310(
if (m_pathController->FindPath(
grec,
local2c,
local20,
@ -457,7 +457,7 @@ MxResult Act3Cop::FUN_10040360()
vecUnk = m_grec->m_position;
m_boundary = m_grec->m_boundary;
m_grec->m_direction = m_unk0xec[3];
m_grec->m_direction = m_local2World[3];
m_grec->m_direction -= vecUnk;
}
else {
@ -470,7 +470,7 @@ MxResult Act3Cop::FUN_10040360()
local128 = *v2;
local128 -= *v1;
local128 *= m_unk0xe4;
local128 *= m_destScale;
local128 += *v1;
local128 *= -1.0f;
local128 += m_grec->m_position;
@ -485,14 +485,14 @@ MxResult Act3Cop::FUN_10040360()
vecUnk = *v2;
vecUnk -= *v1;
vecUnk *= m_unk0xe4;
vecUnk *= m_destScale;
vecUnk += *v1;
}
Vector3 v1(m_unk0xec[0]);
Vector3 v2(m_unk0xec[1]);
Vector3 v3(m_unk0xec[2]);
Vector3 v4(m_unk0xec[3]);
Vector3 v1(m_local2World[0]);
Vector3 v2(m_local2World[1]);
Vector3 v3(m_local2World[2]);
Vector3 v4(m_local2World[3]);
v3 = v4;
v3 -= vecUnk;
@ -501,7 +501,7 @@ MxResult Act3Cop::FUN_10040360()
v1.Unitize();
v2.EqualsCross(v3, v1);
VTable0x9c();
CalculateSpline();
}
return SUCCESS;
@ -509,17 +509,17 @@ MxResult Act3Cop::FUN_10040360()
// FUNCTION: LEGO1 0x10040d20
// FUNCTION: BETA10 0x1001942c
MxResult Act3Cop::VTable0x9c()
MxResult Act3Cop::CalculateSpline()
{
if (m_grec && !m_grec->GetBit1()) {
if (m_grec && !m_grec->HasPath()) {
delete m_grec;
m_grec = NULL;
m_lastTime = Timer()->GetTime();
m_transformTime = Timer()->GetTime();
FUN_10040360();
return SUCCESS;
}
return Act3Actor::VTable0x9c();
return Act3Actor::CalculateSpline();
}
// FUNCTION: LEGO1 0x10040e10
@ -571,7 +571,7 @@ void Act3Brickster::ParseAction(char* p_extra)
// FUNCTION: BETA10 0x100197d7
void Act3Brickster::Animate(float p_time)
{
if (m_lastTime <= m_unk0x20 && m_unk0x20 <= p_time) {
if (m_transformTime <= m_unk0x20 && m_unk0x20 <= p_time) {
SetWorldSpeed(5.0f);
}
@ -619,7 +619,7 @@ void Act3Brickster::Animate(float p_time)
}
else {
MxMatrix local70;
local70 = m_unk0xec;
local70 = m_local2World;
Vector3 local14(local70[0]);
Vector3 local28(local70[1]);
@ -643,7 +643,7 @@ void Act3Brickster::Animate(float p_time)
}
}
m_lastTime = p_time;
m_transformTime = p_time;
break;
case 4:
assert(m_shootAnim && m_bInfo);
@ -664,7 +664,7 @@ void Act3Brickster::Animate(float p_time)
}
else {
MxMatrix locale4;
locale4 = m_unk0xec;
locale4 = m_local2World;
Vector3 local88(locale4[0]);
Vector3 local9c(locale4[1]);
@ -690,7 +690,7 @@ void Act3Brickster::Animate(float p_time)
}
}
m_lastTime = p_time;
m_transformTime = p_time;
break;
case 5:
if (m_grec == NULL) {
@ -794,11 +794,11 @@ MxResult Act3Brickster::FUN_100417c0()
LegoPathEdgeContainer* grec = NULL;
Act3* a3 = (Act3*) m_world;
MxMatrix local70(m_unk0xec);
MxMatrix local70(m_local2World);
Vector3 local28(local70[3]);
Vector3 local20(local70[2]);
if (m_unk0x58 < 8 && m_unk0x24 + 5000.0f < m_lastTime) {
if (m_unk0x58 < 8 && m_unk0x24 + 5000.0f < m_transformTime) {
float local18;
for (MxS32 i = 0; i < MAX_PIZZAS; i++) {
@ -824,7 +824,7 @@ MxResult Act3Brickster::FUN_100417c0()
MxFloat locald8;
LegoPathEdgeContainer *local16c, *local168, *local174, *local170; // unused
if (m_pathController->FUN_10048310(
if (m_pathController->FindPath(
r2,
local28,
local20,
@ -908,7 +908,7 @@ MxResult Act3Brickster::FUN_100417c0()
MxFloat local13c;
LegoPathEdgeContainer *local1c0, *local1bc; // unused
if (m_pathController->FUN_10048310(
if (m_pathController->FindPath(
grec,
local28,
local20,
@ -951,7 +951,7 @@ MxResult Act3Brickster::FUN_100417c0()
vecUnk = m_grec->m_position;
m_boundary = m_grec->m_boundary;
m_grec->m_direction = m_unk0xec[3];
m_grec->m_direction = m_local2World[3];
m_grec->m_direction -= vecUnk;
local150 = m_grec->m_direction;
@ -965,7 +965,7 @@ MxResult Act3Brickster::FUN_100417c0()
local150 = *v2;
local150 -= *v1;
local150 *= m_unk0xe4;
local150 *= m_destScale;
local150 += *v1;
local150 *= -1.0f;
local150 += m_grec->m_position;
@ -980,14 +980,14 @@ MxResult Act3Brickster::FUN_100417c0()
vecUnk = *v2;
vecUnk -= *v1;
vecUnk *= m_unk0xe4;
vecUnk *= m_destScale;
vecUnk += *v1;
}
Vector3 v1(m_unk0xec[0]);
Vector3 v2(m_unk0xec[1]);
Vector3 v3(m_unk0xec[2]);
Vector3 v4(m_unk0xec[3]);
Vector3 v1(m_local2World[0]);
Vector3 v2(m_local2World[1]);
Vector3 v3(m_local2World[2]);
Vector3 v4(m_local2World[3]);
v3 = v4;
v3 -= vecUnk;
@ -996,7 +996,7 @@ MxResult Act3Brickster::FUN_100417c0()
v1.Unitize();
v2.EqualsCross(v3, v1);
VTable0x9c();
CalculateSpline();
if (m_pInfo != NULL) {
m_unk0x38 = 5;
@ -1099,10 +1099,10 @@ MxS32 Act3Brickster::FUN_10042300()
m_destEdge = maxE;
if (m_boundary != boundaries[0]) {
m_unk0xe4 = 1.0 - m_unk0xe4;
m_destScale = 1.0 - m_destScale;
}
VTable0x9c();
CalculateSpline();
}
return -1;
@ -1119,16 +1119,16 @@ void Act3Brickster::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoOrientedEd
// FUNCTION: LEGO1 0x100429d0
// FUNCTION: BETA10 0x1001b75b
MxResult Act3Brickster::VTable0x9c()
MxResult Act3Brickster::CalculateSpline()
{
if (m_grec && !m_grec->GetBit1()) {
if (m_grec && !m_grec->HasPath()) {
delete m_grec;
m_grec = NULL;
m_lastTime = Timer()->GetTime();
m_transformTime = Timer()->GetTime();
return SUCCESS;
}
return Act3Actor::VTable0x9c();
return Act3Actor::CalculateSpline();
}
// FUNCTION: LEGO1 0x10042ab0
@ -1217,7 +1217,7 @@ void Act3Shark::ParseAction(char* p_extra)
token = strtok(NULL, g_parseExtraTokens);
if (token != NULL) {
presenter->FUN_1006d680(this, atof(token));
presenter->CreateROIAndBuildMap(this, atof(token));
}
}

View File

@ -17,7 +17,7 @@ DECOMP_SIZE_ASSERT(Act3Ammo, 0x1a0)
// Initialized at LEGO1 0x100537c0
// GLOBAL: LEGO1 0x10104f08
Mx3DPointFloat Act3Ammo::g_unk0x10104f08 = Mx3DPointFloat(0.0, 5.0, 0.0);
Mx3DPointFloat Act3Ammo::g_hitTranslation = Mx3DPointFloat(0.0, 5.0, 0.0);
// FUNCTION: LEGO1 0x100537f0
// FUNCTION: BETA10 0x1001d648
@ -111,43 +111,44 @@ MxResult Act3Ammo::Create(Act3* p_world, MxU32 p_isPizza, MxS32 p_index)
// FUNCTION: LEGO1 0x10053b40
// FUNCTION: BETA10 0x1001db2a
MxResult Act3Ammo::FUN_10053b40(const Vector3& p_srcLoc, const Vector3& p_srcDir, const Vector3& p_srcUp)
MxResult Act3Ammo::CalculateArc(const Vector3& p_srcLoc, const Vector3& p_srcDir, const Vector3& p_srcUp)
{
assert(p_srcDir[1] != 0);
MxFloat local1c = -(p_srcLoc[1] / p_srcDir[1]);
Mx3DPointFloat local18(p_srcDir);
Mx3DPointFloat local34;
MxFloat yRatioLocDir = -(p_srcLoc[1] / p_srcDir[1]);
Mx3DPointFloat groundPoint(p_srcDir);
Mx3DPointFloat negNormalUp;
local18 *= local1c;
local18 += p_srcLoc;
groundPoint *= yRatioLocDir;
groundPoint += p_srcLoc;
local34[0] = local34[2] = 0.0f;
local34[1] = -1.0f;
negNormalUp[0] = negNormalUp[2] = 0.0f;
negNormalUp[1] = -1.0f;
m_eq[1] = p_srcUp;
m_eq[2] = p_srcLoc;
m_coefficients[1] = p_srcUp;
m_coefficients[2] = p_srcLoc;
Mx3DPointFloat local48(local34);
local48 -= m_eq[1];
Mx3DPointFloat upRelative(negNormalUp);
upRelative -= m_coefficients[1];
for (MxS32 i = 0; i < 3; i++) {
if (local18[0] == p_srcLoc[0]) {
if (groundPoint[0] == p_srcLoc[0]) {
return FAILURE;
}
m_eq[0][i] = (local48[i] * local48[i] + local48[i] * m_eq[1][i] * 2.0f) / ((local18[i] - p_srcLoc[i]) * 4.0f);
m_coefficients[0][i] = (upRelative[i] * upRelative[i] + upRelative[i] * m_coefficients[1][i] * 2.0f) /
((groundPoint[i] - p_srcLoc[i]) * 4.0f);
}
assert(m_eq[0][0] > 0.000001 || m_eq[0][0] < -0.000001);
assert(m_coefficients[0][0] > 0.000001 || m_coefficients[0][0] < -0.000001);
m_unk0x19c = local48[0] / (m_eq[0][0] * 2.0f);
m_apexParameter = upRelative[0] / (m_coefficients[0][0] * 2.0f);
return SUCCESS;
}
// FUNCTION: LEGO1 0x10053cb0
// FUNCTION: BETA10 0x1001ddf4
MxResult Act3Ammo::FUN_10053cb0(LegoPathController* p_p, LegoPathBoundary* p_boundary, MxFloat p_unk0x19c)
MxResult Act3Ammo::Shoot(LegoPathController* p_p, LegoPathBoundary* p_boundary, MxFloat p_apexParameter)
{
assert(p_p);
assert(IsValid());
@ -164,21 +165,21 @@ MxResult Act3Ammo::FUN_10053cb0(LegoPathController* p_p, LegoPathBoundary* p_bou
m_pathController = p_p;
m_boundary = p_boundary;
m_BADuration = 10000.0f;
m_unk0x19c = p_unk0x19c;
m_unk0x7c = 0.0f;
m_lastTime = -1.0f;
m_actorState = c_one;
m_apexParameter = p_apexParameter;
m_traveledDistance = 0.0f;
m_transformTime = -1.0f;
m_actorState = c_ready;
return SUCCESS;
}
// FUNCTION: LEGO1 0x10053d30
// FUNCTION: BETA10 0x1001df73
MxResult Act3Ammo::FUN_10053d30(LegoPathController* p_p, MxFloat p_unk0x19c)
MxResult Act3Ammo::Shoot(LegoPathController* p_p, MxFloat p_apexParameter)
{
assert(p_p);
assert(IsValid());
SetBit4(TRUE);
SetShootWithoutBoundary(TRUE);
if (IsPizza()) {
assert(SoundManager()->GetCacheSoundManager());
@ -191,58 +192,58 @@ MxResult Act3Ammo::FUN_10053d30(LegoPathController* p_p, MxFloat p_unk0x19c)
m_pathController = p_p;
m_BADuration = 10000.0f;
m_unk0x19c = p_unk0x19c;
m_unk0x7c = 0.0f;
m_lastTime = -1.0f;
m_actorState = c_one;
m_apexParameter = p_apexParameter;
m_traveledDistance = 0.0f;
m_transformTime = -1.0f;
m_actorState = c_ready;
return SUCCESS;
}
// FUNCTION: LEGO1 0x10053db0
// FUNCTION: BETA10 0x1001e0f0
MxResult Act3Ammo::FUN_10053db0(float p_param1, Matrix4& p_param2)
MxResult Act3Ammo::CalculateTransformOnCurve(float p_curveParameter, Matrix4& p_transform)
{
float local34 = p_param1 * p_param1;
float curveParameterSquare = p_curveParameter * p_curveParameter;
Vector3 local14(p_param2[0]);
Vector3 local3c(p_param2[1]);
Vector3 localc(p_param2[2]);
Vector3 local30(p_param2[3]);
Mx3DPointFloat local28;
Vector3 right(p_transform[0]);
Vector3 up(p_transform[1]);
Vector3 dir(p_transform[2]);
Vector3 pos(p_transform[3]);
Mx3DPointFloat sndCoeff;
local28 = m_eq[1];
local28 *= p_param1;
local30 = m_eq[0];
local30 *= local34;
local30 += local28;
local30 += m_eq[2];
localc = m_eq[0];
localc *= 2.0f;
localc *= p_param1;
localc += m_eq[1];
localc *= -1.0f;
sndCoeff = m_coefficients[1];
sndCoeff *= p_curveParameter;
pos = m_coefficients[0];
pos *= curveParameterSquare;
pos += sndCoeff;
pos += m_coefficients[2];
dir = m_coefficients[0];
dir *= 2.0f;
dir *= p_curveParameter;
dir += m_coefficients[1];
dir *= -1.0f;
if (localc.Unitize() != 0) {
if (dir.Unitize() != 0) {
assert(0);
return FAILURE;
}
local14[1] = local14[2] = 0.0f;
local14[0] = 1.0f;
local3c.EqualsCross(localc, local14);
right[1] = right[2] = 0.0f;
right[0] = 1.0f;
up.EqualsCross(dir, right);
if (local3c.Unitize() != 0) {
local14[0] = local14[1] = 0.0f;
local14[2] = 1.0f;
local3c.EqualsCross(localc, local14);
if (up.Unitize() != 0) {
right[0] = right[1] = 0.0f;
right[2] = 1.0f;
up.EqualsCross(dir, right);
if (local3c.Unitize() != 0) {
if (up.Unitize() != 0) {
assert(0);
return FAILURE;
}
}
local14.EqualsCross(local3c, localc);
right.EqualsCross(up, dir);
return SUCCESS;
}
@ -254,19 +255,19 @@ void Act3Ammo::Animate(float p_time)
switch (m_actorState & c_maxState) {
case c_initial:
case c_one:
case c_ready:
break;
case c_two:
m_unk0x158 = p_time + 2000.0f;
m_actorState = c_three;
case c_hit:
m_rotateTimeout = p_time + 2000.0f;
m_actorState = c_hitAnimation;
return;
case c_three:
case c_hitAnimation:
MxMatrix transform;
Vector3 positionRef(transform[3]);
transform = m_roi->GetLocal2World();
if (m_unk0x158 > p_time) {
if (m_rotateTimeout > p_time) {
Mx3DPointFloat position;
position = positionRef;
@ -279,9 +280,9 @@ void Act3Ammo::Animate(float p_time)
}
else {
m_actorState = c_initial;
m_unk0x158 = 0;
m_rotateTimeout = 0;
positionRef -= g_unk0x10104f08;
positionRef -= g_hitTranslation;
m_roi->SetLocal2World(transform);
m_roi->WrappedUpdateWorldData();
return;
@ -292,90 +293,90 @@ void Act3Ammo::Animate(float p_time)
return;
}
if (m_lastTime < 0.0f) {
m_lastTime = p_time;
m_unk0x7c = 0.0f;
if (m_transformTime < 0.0f) {
m_transformTime = p_time;
m_traveledDistance = 0.0f;
}
MxMatrix local104;
MxMatrix local60;
MxMatrix transform;
MxMatrix additionalTransform;
float f = (m_BADuration - m_unk0x7c) / m_worldSpeed + m_lastTime;
float f = (m_BADuration - m_traveledDistance) / m_worldSpeed + m_transformTime;
undefined4 localb4 = 0;
undefined4 localbc = 0;
MxU32 local14 = FALSE;
MxU32 localb8 = FALSE;
undefined4 unused1 = 0;
undefined4 unused2 = 0;
MxU32 annihilated = FALSE;
MxU32 reachedTarget = FALSE;
if (f > p_time) {
m_actorTime = (p_time - m_lastTime) * m_worldSpeed + m_actorTime;
m_unk0x7c = (p_time - m_lastTime) * m_worldSpeed + m_unk0x7c;
m_lastTime = p_time;
m_actorTime = (p_time - m_transformTime) * m_worldSpeed + m_actorTime;
m_traveledDistance = (p_time - m_transformTime) * m_worldSpeed + m_traveledDistance;
m_transformTime = p_time;
}
else {
localb8 = TRUE;
m_unk0x7c = m_BADuration;
m_lastTime = p_time;
reachedTarget = TRUE;
m_traveledDistance = m_BADuration;
m_transformTime = p_time;
}
local104.SetIdentity();
transform.SetIdentity();
MxResult r = FUN_10053db0((m_unk0x7c / m_BADuration) * m_unk0x19c, local104);
MxResult r = CalculateTransformOnCurve((m_traveledDistance / m_BADuration) * m_apexParameter, transform);
assert(r == 0); // SUCCESS
local60.SetIdentity();
additionalTransform.SetIdentity();
if (IsPizza()) {
local60.Scale(2.0f, 2.0f, 2.0f);
additionalTransform.Scale(2.0f, 2.0f, 2.0f);
}
else {
local60.Scale(5.0f, 5.0f, 5.0f);
additionalTransform.Scale(5.0f, 5.0f, 5.0f);
}
if (localb8) {
if (reachedTarget) {
if (m_boundary != NULL) {
Vector3 local17c(local104[0]);
Vector3 local184(local104[1]);
Vector3 local174(local104[2]);
Vector3 right(transform[0]);
Vector3 up(transform[1]);
Vector3 dir(transform[2]);
if (IsPizza()) {
local184 = *m_boundary->GetUp();
local17c[0] = 1.0f;
local17c[1] = local17c[2] = 0.0f;
local174.EqualsCross(local17c, local184);
local174.Unitize();
local17c.EqualsCross(local184, local174);
up = *m_boundary->GetUp();
right[0] = 1.0f;
right[1] = right[2] = 0.0f;
dir.EqualsCross(right, up);
dir.Unitize();
right.EqualsCross(up, dir);
}
else {
local17c = *m_boundary->GetUp();
local184[0] = 1.0f;
local184[1] = local184[2] = 0.0f;
local174.EqualsCross(local17c, local184);
local174.Unitize();
local184.EqualsCross(local174, local17c);
right = *m_boundary->GetUp();
up[0] = 1.0f;
up[1] = up[2] = 0.0f;
dir.EqualsCross(right, up);
dir.Unitize();
up.EqualsCross(dir, right);
}
}
m_actorState = c_initial;
}
else {
local60.RotateX(m_actorTime / 10.0f);
local60.RotateY(m_actorTime / 6.0f);
additionalTransform.RotateX(m_actorTime / 10.0f);
additionalTransform.RotateY(m_actorTime / 6.0f);
}
MxMatrix localb0(local104);
local104.Product(local60, localb0);
m_roi->SetLocal2World(local104);
MxMatrix transformCopy(transform);
transform.Product(additionalTransform, transformCopy);
m_roi->SetLocal2World(transform);
m_roi->WrappedUpdateWorldData();
if (m_BADuration <= m_unk0x7c) {
if (m_BADuration <= m_traveledDistance) {
m_worldSpeed = 0.0f;
}
Vector3 local68(local104[3]);
Vector3 position(transform[3]);
if (localb8) {
if (IsBit4()) {
if (reachedTarget) {
if (IsShootWithoutBoundary()) {
if (IsPizza()) {
m_world->RemovePizza(*this);
m_world->TriggerHitSound(2);
@ -414,16 +415,16 @@ void Act3Ammo::Animate(float p_time)
assert(r);
if (!strncmp(r->GetName(), "pammo", 5)) {
Mx3DPointFloat local1c8;
Mx3DPointFloat local1b4;
Mx3DPointFloat otherPosition;
Mx3DPointFloat distance;
local1c8 = r->GetLocal2World()[3];
local1b4 = m_roi->GetLocal2World()[3];
otherPosition = r->GetLocal2World()[3];
distance = m_roi->GetLocal2World()[3];
local1b4 -= local1c8;
distance -= otherPosition;
float radius = r->GetWorldBoundingSphere().Radius();
if (local1b4.LenSquared() <= radius * radius) {
if (distance.LenSquared() <= radius * radius) {
MxS32 index = -1;
if (sscanf(r->GetName(), "pammo%d", &index) != 1) {
assert(0);
@ -444,22 +445,22 @@ void Act3Ammo::Animate(float p_time)
assert(SoundManager()->GetCacheSoundManager());
SoundManager()->GetCacheSoundManager()->Play("dnhitpz", NULL, FALSE);
m_world->RemoveDonut(*this);
local14 = TRUE;
annihilated = TRUE;
break;
}
}
}
else if (!strncmp(r->GetName(), "dammo", 5)) {
Mx3DPointFloat local1f8;
Mx3DPointFloat local1e4;
Mx3DPointFloat otherPosition;
Mx3DPointFloat distance;
local1f8 = r->GetLocal2World()[3];
local1e4 = m_roi->GetLocal2World()[3];
otherPosition = r->GetLocal2World()[3];
distance = m_roi->GetLocal2World()[3];
local1e4 -= local1f8;
distance -= otherPosition;
float radius = r->GetWorldBoundingSphere().Radius();
if (local1e4.LenSquared() <= radius * radius) {
if (distance.LenSquared() <= radius * radius) {
MxS32 index = -1;
if (sscanf(r->GetName(), "dammo%d", &index) != 1) {
assert(0);
@ -473,19 +474,19 @@ void Act3Ammo::Animate(float p_time)
assert(SoundManager()->GetCacheSoundManager());
SoundManager()->GetCacheSoundManager()->Play("pzhitdn", NULL, FALSE);
m_world->RemovePizza(*this);
local14 = TRUE;
annihilated = TRUE;
break;
}
}
}
}
if (!local14) {
if (!annihilated) {
if (IsPizza()) {
m_world->FUN_10073360(*this, local68);
m_world->FUN_10073360(*this, position);
}
else {
m_world->FUN_10073390(*this, local68);
m_world->FUN_10073390(*this, position);
}
m_worldSpeed = -1.0f;

View File

@ -19,8 +19,8 @@ DECOMP_SIZE_ASSERT(Bike, 0x164)
Bike::Bike()
{
m_maxLinearVel = 20.0;
m_unk0x150 = 3.0;
m_unk0x148 = 1;
m_linearRotationRatio = 3.0;
m_canRotate = 1;
}
// FUNCTION: LEGO1 0x100768f0

View File

@ -13,15 +13,15 @@ DECOMP_SIZE_ASSERT(Doors, 0x1f8)
// GLOBAL: LEGO1 0x100d8e7c
// GLOBAL: BETA10 0x101b954c
MxFloat g_unk0x100d8e7c = 1000.0f;
MxFloat g_timeMoving = 1000.0f;
// GLOBAL: LEGO1 0x100d8e80
// GLOBAL: BETA10 0x101b9550
MxFloat g_unk0x100d8e80 = 4000.0f;
MxFloat g_timeOpened = 4000.0f;
// GLOBAL: LEGO1 0x100d8e84
// GLOBAL: BETA10 0x101b9554
MxFloat g_unk0x100d8e84 = 6000.0f;
MxFloat g_totalTime = 6000.0f; // = g_timeMoving + g_totalTime + g_timeMoving
// FUNCTION: LEGO1 0x10066100
// FUNCTION: BETA10 0x10026850
@ -29,36 +29,36 @@ MxResult Doors::HitActor(LegoPathActor* p_actor, MxBool p_bool)
{
assert(m_ltDoor && m_rtDoor);
if (m_unk0x154 == 1) {
m_unk0x154 = 2;
m_unk0x158 = Timer()->GetTime();
m_ltDoorLocal = m_ltDoor->GetLocal2World();
m_rtDoorLocal = m_rtDoor->GetLocal2World();
if (m_state == e_closed) {
m_state = e_cycling;
m_hitTime = Timer()->GetTime();
m_ltDoorOriginalLocal = m_ltDoor->GetLocal2World();
m_rtDoorOriginalLocal = m_rtDoor->GetLocal2World();
}
return m_unk0x1f4 < 0.001 ? SUCCESS : FAILURE;
return m_angle < 0.001 ? SUCCESS : FAILURE;
}
// FUNCTION: LEGO1 0x10066190
// FUNCTION: BETA10 0x1002696b
MxFloat Doors::VTable0xcc(float p_time)
MxFloat Doors::CalculateAngle(float p_time)
{
MxFloat fVar1;
MxFloat timeSinceHit;
fVar1 = p_time - m_unk0x158;
timeSinceHit = p_time - m_hitTime;
if (fVar1 <= 0.0f) {
if (timeSinceHit <= 0.0f) {
return 0.0f;
}
if (fVar1 <= g_unk0x100d8e7c) {
return fVar1 * 1.570796 / g_unk0x100d8e7c;
if (timeSinceHit <= g_timeMoving) {
return timeSinceHit * 1.570796 / g_timeMoving;
}
else if (fVar1 <= g_unk0x100d8e7c + g_unk0x100d8e80) {
else if (timeSinceHit <= g_timeMoving + g_timeOpened) {
return 1.570796012878418; // Pi / 2
}
else if (fVar1 <= g_unk0x100d8e84) {
return (1.0 - ((fVar1 - g_unk0x100d8e80) - g_unk0x100d8e7c) / g_unk0x100d8e7c) * 1.570796;
else if (timeSinceHit <= g_totalTime) {
return (1.0 - ((timeSinceHit - g_timeOpened) - g_timeMoving) / g_timeMoving) * 1.570796;
}
return 0.0f;
@ -71,46 +71,46 @@ void Doors::Animate(float p_time)
assert(m_ltDoor && m_rtDoor);
// TODO: Match
m_roi->SetVisibility(m_boundary->GetFlag0x10());
m_roi->SetVisibility(m_boundary->GetVisibility());
switch (m_unk0x154) {
case 0:
m_unk0x154 = 1;
switch (m_state) {
case e_none:
m_state = e_closed;
m_actorState = c_initial;
break;
case 1:
case e_closed:
break;
case 2:
float local8 = VTable0xcc(p_time);
case e_cycling:
float angle = CalculateAngle(p_time);
if (local8 > 0.0f) {
MxMatrix local58(m_ltDoorLocal);
Vector3 local10(local58[3]);
if (angle > 0.0f) {
MxMatrix transform(m_ltDoorOriginalLocal);
Vector3 position(transform[3]);
local10.Clear();
local58.RotateY(-local8);
local10 = m_ltDoorLocal[3];
m_ltDoor->SetLocal2World(local58);
position.Clear();
transform.RotateY(-angle);
position = m_ltDoorOriginalLocal[3];
m_ltDoor->SetLocal2World(transform);
m_ltDoor->WrappedUpdateWorldData();
local58 = m_rtDoorLocal;
local10.Clear();
local58.RotateY(local8);
local10 = m_rtDoorLocal[3];
m_rtDoor->SetLocal2World(local58);
transform = m_rtDoorOriginalLocal;
position.Clear();
transform.RotateY(angle);
position = m_rtDoorOriginalLocal[3];
m_rtDoor->SetLocal2World(transform);
m_rtDoor->WrappedUpdateWorldData();
m_unk0x1f4 = local8;
m_angle = angle;
}
if (m_unk0x158 + g_unk0x100d8e84 < p_time) {
m_ltDoor->SetLocal2World(m_ltDoorLocal);
m_rtDoor->SetLocal2World(m_rtDoorLocal);
if (m_hitTime + g_totalTime < p_time) {
m_ltDoor->SetLocal2World(m_ltDoorOriginalLocal);
m_rtDoor->SetLocal2World(m_rtDoorOriginalLocal);
m_ltDoor->WrappedUpdateWorldData();
m_rtDoor->WrappedUpdateWorldData();
m_unk0x154 = 1;
m_state = e_closed;
m_actorState = c_initial;
m_unk0x1f4 = 0;
m_angle = 0;
}
}
}

View File

@ -384,7 +384,7 @@ MxLong Helicopter::HandleEndAnim(LegoEndAnimNotificationParam& p_param)
}
// FUNCTION: LEGO1 0x10003e90
void Helicopter::VTable0x74(Matrix4& p_transform)
void Helicopter::ApplyTransform(Matrix4& p_transform)
{
if (m_userNavFlag) {
m_roi->UpdateTransformationRelativeToParent(p_transform);

View File

@ -92,7 +92,7 @@ void IslePathActor::Enter()
NavController()->ResetMaxLinearVel(m_maxLinearVel);
SetUserActor(this);
FUN_1001b660();
TurnAround();
TransformPointOfView();
}
}
@ -151,7 +151,7 @@ void IslePathActor::Exit()
GameState()->m_currentArea = LegoGameState::Area::e_vehicleExited;
}
FUN_1001b660();
TurnAround();
TransformPointOfView();
ResetViewVelocity();
}
@ -611,7 +611,7 @@ void IslePathActor::SpawnPlayer(LegoGameState::Area p_area, MxBool p_enter, MxU8
}
// FUNCTION: LEGO1 0x1001b5b0
void IslePathActor::VTable0xec(MxMatrix p_transform, LegoPathBoundary* p_boundary, MxBool p_reset)
void IslePathActor::UpdateWorld(MxMatrix p_transform, LegoPathBoundary* p_boundary, MxBool p_reset)
{
if (m_world) {
m_world->RemoveActor(this);
@ -639,15 +639,15 @@ void IslePathActor::VTable0xec(MxMatrix p_transform, LegoPathBoundary* p_boundar
// FUNCTION: LEGO1 0x1001b660
// FUNCTION: BETA10 0x10036ea2
void IslePathActor::FUN_1001b660()
void IslePathActor::TurnAround()
{
MxMatrix transform(m_roi->GetLocal2World());
Vector3 position(transform[0]);
Vector3 direction(transform[1]);
Vector3 up(transform[2]);
Vector3 right(transform[0]);
Vector3 up(transform[1]);
Vector3 direction(transform[2]);
up *= -1.0f;
position.EqualsCross(direction, up);
direction *= -1.0f;
right.EqualsCross(up, direction);
m_roi->SetLocal2World(transform);
m_roi->WrappedUpdateWorldData();
}

View File

@ -35,8 +35,8 @@ const char* g_varJSWNSHY5 = "c_jswnshy5";
Jetski::Jetski()
{
m_maxLinearVel = 25.0;
m_unk0x150 = 2.0;
m_unk0x148 = 1;
m_linearRotationRatio = 2.0;
m_canRotate = 1;
}
// FUNCTION: LEGO1 0x1007e630

View File

@ -24,8 +24,8 @@ DECOMP_SIZE_ASSERT(Motocycle, 0x16c)
Motocycle::Motocycle()
{
m_maxLinearVel = 40.0;
m_unk0x150 = 1.75;
m_unk0x148 = 1;
m_linearRotationRatio = 1.75;
m_canRotate = 1;
m_fuel = 1.0;
}

View File

@ -22,8 +22,8 @@ SkateBoard::SkateBoard()
{
m_pizzaVisible = FALSE;
m_maxLinearVel = 15.0;
m_unk0x150 = 3.5;
m_unk0x148 = 1;
m_linearRotationRatio = 3.5;
m_canRotate = 1;
NotificationManager()->Register(this);
}

View File

@ -123,7 +123,7 @@ void LegoCarBuildAnimPresenter::PutFrame()
MoveShelfForward();
case e_stopped:
if (m_carBuildEntity->GetROI()) {
FUN_1006b9a0(m_anim, m_shelfFrameBuffer, NULL);
ApplyTransformWithVisibilityAndCam(m_anim, m_shelfFrameBuffer, NULL);
}
default:
break;
@ -591,7 +591,7 @@ void LegoCarBuildAnimPresenter::RotateAroundYAxis(MxFloat p_angle)
m_platformAnimNodeData->GetRotationKey(0)->SetAngle(newRotation[3]);
if (m_carBuildEntity->GetROI()) {
FUN_1006b9a0(&m_platformAnim, m_shelfFrameBuffer, NULL);
ApplyTransformWithVisibilityAndCam(&m_platformAnim, m_shelfFrameBuffer, NULL);
}
}
}

View File

@ -26,7 +26,7 @@ void LegoActionControlPresenter::ReadyTickle()
m_subscriber->FreeDataChunk(chunk);
if (m_compositePresenter) {
if (m_action->GetDuration() == -1 || m_action->GetFlags() & 1) {
m_compositePresenter->VTable0x60(this);
m_compositePresenter->AdvanceSerialAction(this);
}
}
}
@ -36,11 +36,11 @@ void LegoActionControlPresenter::ReadyTickle()
void LegoActionControlPresenter::RepeatingTickle()
{
if (IsEnabled()) {
if (m_unk0x50 == 0) {
if (m_actionType == 0) {
ParseExtra();
}
InvokeAction(m_unk0x50, MxAtomId(m_unk0x54.GetData(), e_lowerCase2), m_unk0x64, NULL);
InvokeAction(m_actionType, MxAtomId(m_sourceName.GetData(), e_lowerCase2), m_streamId, NULL);
ProgressTickleState(e_done);
}
}
@ -84,15 +84,15 @@ void LegoActionControlPresenter::ParseExtra()
char output[1024];
if (KeyValueStringParse(output, g_strACTION, extraCopy)) {
m_unk0x50 = MatchActionString(strtok(output, g_parseExtraTokens));
m_actionType = MatchActionString(strtok(output, g_parseExtraTokens));
if (m_unk0x50 != Extra::ActionType::e_exit) {
if (m_actionType != Extra::ActionType::e_exit) {
MakeSourceName(extraCopy, strtok(NULL, g_parseExtraTokens));
m_unk0x54 = extraCopy;
m_unk0x54.ToLowerCase();
if (m_unk0x50 != Extra::ActionType::e_run) {
m_unk0x64 = atoi(strtok(NULL, g_parseExtraTokens));
m_sourceName = extraCopy;
m_sourceName.ToLowerCase();
if (m_actionType != Extra::ActionType::e_run) {
m_streamId = atoi(strtok(NULL, g_parseExtraTokens));
}
}
}

View File

@ -315,7 +315,7 @@ MxS32 g_legoAnimationManagerConfig = 1;
float g_unk0x100f7500 = 0.1f;
// GLOBAL: LEGO1 0x100f7504
MxS32 g_unk0x100f7504 = 0;
MxS32 g_pathWalkingModeSelector = 0;
// FUNCTION: LEGO1 0x1005eb50
void LegoAnimationManager::configureLegoAnimationManager(MxS32 p_legoAnimationManagerConfig)
@ -1933,10 +1933,10 @@ void LegoAnimationManager::AddExtra(MxS32 p_location, MxBool p_und)
}
if (i != m_numAllowedExtras) {
MxU8 und = SDL_rand(2) != 0 ? 1 : 2;
MxU8 pathWalkingMode = SDL_rand(2) != 0 ? 1 : 2;
MxBool bool1, bool2;
switch (g_unk0x100f7504 % 4) {
switch (g_pathWalkingModeSelector % 4) {
case 0:
bool1 = FALSE;
bool2 = FALSE;
@ -1954,7 +1954,7 @@ void LegoAnimationManager::AddExtra(MxS32 p_location, MxBool p_und)
if (p_location < 0) {
boundary = new LegoLocation::Boundary;
if (!FUN_10064120(boundary, und == 2, bool2)) {
if (!FUN_10064120(boundary, pathWalkingMode == 2, bool2)) {
delete boundary;
boundary = NULL;
}
@ -2008,19 +2008,19 @@ void LegoAnimationManager::AddExtra(MxS32 p_location, MxBool p_und)
g_characters[m_lastExtraCharacterId].m_name
);
switch (g_unk0x100f7504++ % 4) {
switch (g_pathWalkingModeSelector++ % 4) {
case 0:
actor->SetUnknown0x0c(und != 1 ? 1 : 2);
actor->SetPathWalkingMode(pathWalkingMode != 1 ? 1 : 2);
break;
case 1: {
actor->SetUnknown0x0c(und);
actor->SetPathWalkingMode(pathWalkingMode);
MxS32 src = boundary->m_src;
boundary->m_src = boundary->m_dest;
boundary->m_dest = src;
break;
}
default:
actor->SetUnknown0x0c(und);
actor->SetPathWalkingMode(pathWalkingMode);
break;
}
@ -2190,21 +2190,21 @@ MxBool LegoAnimationManager::FUN_10062e20(LegoROI* p_roi, LegoAnimPresenter* p_p
MxResult result = 1; // Not a valid MxResult value
if (!local24) {
MxU8 unk0x0c;
MxU8 pathWalkingMode;
switch (SDL_rand(3)) {
case 0:
unk0x0c = 1;
pathWalkingMode = 1;
break;
case 1:
unk0x0c = 2;
pathWalkingMode = 2;
break;
case 2:
unk0x0c = 0;
pathWalkingMode = 0;
break;
}
actor->SetUnknown0x0c(unk0x0c);
actor->SetPathWalkingMode(pathWalkingMode);
Mx3DPointFloat position;
Mx3DPointFloat direction;
@ -2390,7 +2390,7 @@ MxBool LegoAnimationManager::FUN_10063b90(LegoWorld* p_world, LegoExtraActor* p_
presenter = (LegoLocomotionAnimPresenter*) p_world->Find("LegoAnimPresenter", vehicleWC);
if (presenter != NULL) {
presenter->FUN_1006d680(p_actor, 1.7f);
presenter->CreateROIAndBuildMap(p_actor, 1.7f);
}
g_vehicles[g_characters[p_characterId].m_vehicleId].m_unk0x04 = FALSE;
@ -2403,7 +2403,7 @@ MxBool LegoAnimationManager::FUN_10063b90(LegoWorld* p_world, LegoExtraActor* p_
presenter = (LegoLocomotionAnimPresenter*) p_world->Find("LegoAnimPresenter", vehicleWC);
if (presenter != NULL) {
presenter->FUN_1006d680(p_actor, 0.7f);
presenter->CreateROIAndBuildMap(p_actor, 0.7f);
}
}
@ -2416,7 +2416,7 @@ MxBool LegoAnimationManager::FUN_10063b90(LegoWorld* p_world, LegoExtraActor* p_
presenter = (LegoLocomotionAnimPresenter*) p_world->Find("LegoAnimPresenter", vehicleWC);
if (presenter != NULL) {
presenter->FUN_1006d680(p_actor, 4.0f);
presenter->CreateROIAndBuildMap(p_actor, 4.0f);
}
}
@ -2429,7 +2429,7 @@ MxBool LegoAnimationManager::FUN_10063b90(LegoWorld* p_world, LegoExtraActor* p_
presenter = (LegoLocomotionAnimPresenter*) p_world->Find("LegoAnimPresenter", vehicleWC);
if (presenter != NULL) {
presenter->FUN_1006d680(p_actor, 0.0f);
presenter->CreateROIAndBuildMap(p_actor, 0.0f);
}
}
@ -2701,8 +2701,8 @@ MxResult LegoAnimationManager::FUN_10064380(
}
if (actor != NULL) {
MxU8 unk0x0c = SDL_rand(2) != 0 ? 1 : 2;
actor->SetUnknown0x0c(unk0x0c);
MxU8 pathWalkingMode = SDL_rand(2) != 0 ? 1 : 2;
actor->SetPathWalkingMode(pathWalkingMode);
actor->SetWorldSpeed(0.0f);
if (world->PlaceActor(actor, p_boundaryName, p_src, p_srcScale, p_dest, p_destScale) != SUCCESS) {
@ -2718,12 +2718,12 @@ MxResult LegoAnimationManager::FUN_10064380(
LegoLocomotionAnimPresenter* presenter =
(LegoLocomotionAnimPresenter*) world->Find("LegoAnimPresenter", cycles[p_undIdx1]);
if (presenter != NULL) {
presenter->FUN_1006d680(actor, 0.0f);
presenter->CreateROIAndBuildMap(actor, 0.0f);
}
presenter = (LegoLocomotionAnimPresenter*) world->Find("LegoAnimPresenter", cycles[p_undIdx2]);
if (presenter != NULL) {
presenter->FUN_1006d680(actor, 4.0f);
presenter->CreateROIAndBuildMap(actor, 4.0f);
}
m_extras[i].m_unk0x08 = Timer()->GetTime();

View File

@ -152,7 +152,7 @@ void LegoAnimMMPresenter::ReadyTickle()
}
if (m_tranInfo != NULL && m_tranInfo->m_unk0x0c != NULL) {
m_presenter->VTable0xa0(*m_tranInfo->m_unk0x0c);
m_presenter->SetTransform(*m_tranInfo->m_unk0x0c);
}
if (m_presenter != NULL) {
@ -168,7 +168,7 @@ void LegoAnimMMPresenter::StartingTickle()
{
if (m_presenter == NULL || m_presenter->GetCurrentTickleState() == e_idle) {
if (m_tranInfo != NULL && m_tranInfo->m_unk0x08 != NULL) {
m_presenter->FUN_1006b140(m_tranInfo->m_unk0x08);
m_presenter->CopyTransform(m_tranInfo->m_unk0x08);
}
m_unk0x50 = Timer()->GetTime();
@ -225,7 +225,7 @@ MxLong LegoAnimMMPresenter::Notify(MxParam& p_param)
}
// FUNCTION: LEGO1 0x1004b360
void LegoAnimMMPresenter::VTable0x60(MxPresenter* p_presenter)
void LegoAnimMMPresenter::AdvanceSerialAction(MxPresenter* p_presenter)
{
if (m_presenter == p_presenter && ((MxU8) p_presenter->GetCurrentTickleState() == MxPresenter::e_streaming ||
(MxU8) p_presenter->GetCurrentTickleState() == MxPresenter::e_done)) {
@ -316,7 +316,7 @@ MxBool LegoAnimMMPresenter::FUN_1004b450()
MxBool LegoAnimMMPresenter::FUN_1004b530(MxLong p_time)
{
if (m_presenter != NULL) {
m_presenter->FUN_1006afc0(m_unk0x68, 0);
m_presenter->GetTransforms(m_unk0x68, 0);
m_roiMap = m_presenter->GetROIMap(m_roiMapSize);
m_roiMapSize++;
}
@ -403,7 +403,7 @@ MxBool LegoAnimMMPresenter::FUN_1004b610(MxLong p_time)
m_action->SetTimeStarted(Timer()->GetTime());
if (m_compositePresenter != NULL) {
m_compositePresenter->VTable0x60(this);
m_compositePresenter->AdvanceSerialAction(this);
}
return TRUE;
@ -471,10 +471,10 @@ MxBool LegoAnimMMPresenter::FUN_1004b6d0(MxLong p_time)
}
#ifdef BETA10
actor->VTable0xa8();
actor->ApplyLocal2World();
#else
if (m_tranInfo->m_unk0x29) {
actor->VTable0xa8();
actor->ApplyLocal2World();
}
#endif
}
@ -498,7 +498,7 @@ void LegoAnimMMPresenter::FUN_1004b840()
MxDSAction* action = m_action;
if (m_presenter != NULL) {
m_presenter->FUN_1006c7a0();
m_presenter->ApplyFinishedTransform();
}
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {

View File

@ -0,0 +1,156 @@
#include "legotesttimer.h"
#include "legoeventnotificationparam.h"
#include "legoinputmanager.h"
#include "misc.h"
#include "mxnotificationparam.h"
#include <stdio.h>
// FUNCTION: BETA10 0x100d1030
LegoTestTimer::LegoTestTimer(LegoS32 p_numTimers, LegoS32 p_interval, LegoS32 p_numBins, LegoS32 p_type)
{
m_enable = FALSE;
m_keyRegistered = FALSE;
if (p_interval > 0) {
m_numTimers = p_numTimers;
m_interval = p_interval;
m_numBins = p_numBins / m_interval;
m_lastTime = new LegoS32[m_numTimers];
m_totalTime = new LegoS32[m_numTimers];
m_timers = new LegoS32*[m_numTimers];
for (int i = 0; i < m_numTimers; i++) {
m_lastTime[i] = -1;
m_timers[i] = new LegoS32[m_numBins];
for (int j = 0; j < m_numBins; j++) {
m_timers[i][j] = 0;
}
}
}
else {
m_numTimers = 0;
m_interval = 0;
m_numBins = 0;
m_lastTime = NULL;
m_totalTime = NULL;
m_timers = NULL;
}
}
// FUNCTION: BETA10 0x100d11ee
LegoTestTimer::~LegoTestTimer()
{
if (m_keyRegistered && InputManager()) {
InputManager()->UnRegister(this);
}
m_enable = FALSE;
if (m_numTimers != 0) {
delete[] m_lastTime;
delete[] m_totalTime;
for (int i = 0; i < m_numTimers; i++) {
delete m_timers[i];
}
delete[] m_timers;
}
}
// FUNCTION: BETA10 0x100d132c
void LegoTestTimer::Tick(LegoS32 p_timer)
{
if (m_enable) {
MxULong time = timeGetTime();
LegoS32 prev = p_timer ? p_timer - 1 : 0;
if (m_lastTime[p_timer] == -1) {
m_lastTime[p_timer] = time;
m_totalTime[p_timer] = 0;
for (int i = 0; i < m_numBins; i++) {
m_timers[p_timer][i] = 0;
}
}
else {
LegoS32 dtim = time - m_lastTime[prev];
if (dtim < 0) {
dtim = 0;
}
m_lastTime[p_timer] = time;
LegoS32 binIndex = dtim / m_interval;
if (binIndex >= m_numBins) {
binIndex = m_numBins - 1;
}
m_timers[p_timer][binIndex]++;
m_totalTime[p_timer] += dtim;
}
}
else if (!m_keyRegistered) {
InputManager()->Register(this);
m_keyRegistered = TRUE;
}
}
// FUNCTION: BETA10 0x100d148f
void LegoTestTimer::Print()
{
FILE* f = fopen("\\TEST_TIME.TXT", "w");
if (f) {
int i;
fprintf(f, "timer");
for (i = 0; i < m_numTimers; i++) {
fprintf(f, "%8d ", i);
}
fprintf(f, "\n");
for (int k = 0; k < m_numBins; k++) {
fprintf(f, "%3d: ", m_interval * (k + 1));
for (int j = 0; j < m_numTimers; j++) {
fprintf(f, "%8d ", m_timers[j][k]);
}
fprintf(f, "\n");
}
fprintf(f, "ttime");
for (i = 0; i < m_numTimers; i++) {
fprintf(f, "%8d ", m_totalTime[i]);
}
fclose(f);
}
ResetAtNextTick();
}
// FUNCTION: BETA10 0x100d161e
void LegoTestTimer::ResetAtNextTick()
{
for (int i = 0; i < m_numTimers; i++) {
m_lastTime[i] = -1;
}
}
// FUNCTION: BETA10 0x100d1667
MxLong LegoTestTimer::Notify(MxParam& p_param)
{
if (((MxNotificationParam&) p_param).GetNotification() == c_notificationKeyPress) {
MxU8 key = ((LegoEventNotificationParam&) p_param).GetKey();
if (key == 's' || key == 'S') {
ResetAtNextTick();
m_enable = TRUE;
}
else if (key == 'p' || key == 'P') {
m_enable = FALSE;
Print();
}
}
return 0;
}

View File

@ -15,8 +15,8 @@ DECOMP_SIZE_ASSERT(MxCompositeMediaPresenter, 0x50)
// FUNCTION: LEGO1 0x10073ea0
MxCompositeMediaPresenter::MxCompositeMediaPresenter()
{
m_unk0x4c = 0;
m_unk0x4e = FALSE;
m_remainingChildren = 0;
m_allChildrenStreaming = FALSE;
VideoManager()->RegisterPresenter(*this);
}
@ -99,25 +99,25 @@ void MxCompositeMediaPresenter::StartingTickle()
{
AUTOLOCK(m_criticalSection);
if (!m_unk0x4e) {
if (!m_allChildrenStreaming) {
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
if ((*it)->GetCurrentTickleState() < e_streaming) {
(*it)->Tickle();
if ((*it)->GetCurrentTickleState() == e_streaming ||
((*it)->GetAction() && (*it)->GetAction()->GetStartTime())) {
m_unk0x4c++;
m_remainingChildren++;
}
}
}
if (m_list.size() == m_unk0x4c) {
m_unk0x4e = TRUE;
m_unk0x4c = 0;
if (m_list.size() == m_remainingChildren) {
m_allChildrenStreaming = TRUE;
m_remainingChildren = 0;
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
if (!(*it)->GetAction()->GetStartTime()) {
m_unk0x4c++;
m_remainingChildren++;
}
}
}
@ -128,11 +128,11 @@ void MxCompositeMediaPresenter::StartingTickle()
!((*it)->GetAction()->GetFlags() & MxDSAction::c_bit9)) {
(*it)->Tickle();
(*it)->GetAction()->SetFlags((*it)->GetAction()->GetFlags() | MxDSAction::c_bit9);
m_unk0x4c--;
m_remainingChildren--;
}
}
if (!m_unk0x4c) {
if (!m_remainingChildren) {
ProgressTickleState(e_streaming);
MxLong time = Timer()->GetTime();
m_action->SetTimeStarted(time);

View File

@ -142,11 +142,11 @@ LegoNavController::LegoNavController()
m_linearAccel = 0.0f;
m_rotationalAccel = 0.0f;
m_trackDefault = FALSE;
m_unk0x5d = FALSE;
m_keyPressed = FALSE;
m_isAccelerating = FALSE;
m_unk0x64 = 0.0f;
m_unk0x68 = 0.0f;
m_unk0x60 = 0.0f;
m_additionalScale = 0.0f;
m_additionalRotationY = 0.0f;
m_additionalHeightOffset = 0.0f;
m_lastTime = Timer()->GetTime();
@ -330,7 +330,7 @@ MxBool LegoNavController::CalculateNewPosDir(
const Vector3& p_curDir,
Vector3& p_newPos,
Vector3& p_newDir,
const Vector3* p_und
const Vector3* p_up
)
{
if (!g_isWorldActive) {
@ -338,14 +338,14 @@ MxBool LegoNavController::CalculateNewPosDir(
}
MxBool changed = FALSE;
MxBool und = FALSE;
MxBool rotatedY = FALSE;
MxTime currentTime = Timer()->GetTime();
float deltaTime = Min((currentTime - m_lastTime) / 1000.0, 1. / 10.);
m_lastTime = currentTime;
if (ProcessKeyboardInput() == FAILURE) {
ProcessJoystickInput(und);
ProcessJoystickInput(rotatedY);
}
if (m_useRotationalVel) {
@ -357,7 +357,7 @@ MxBool LegoNavController::CalculateNewPosDir(
m_linearVel = CalculateNewVel(m_targetLinearVel, m_linearVel, m_linearAccel, deltaTime);
if (und || (Abs(m_rotationalVel) > m_zeroThreshold) || (Abs(m_linearVel) > m_zeroThreshold)) {
if (rotatedY || (Abs(m_rotationalVel) > m_zeroThreshold) || (Abs(m_linearVel) > m_zeroThreshold)) {
float rot_mat[3][3];
Mx3DPointFloat delta_pos, new_dir, new_pos;
@ -376,7 +376,7 @@ MxBool LegoNavController::CalculateNewPosDir(
delta_rad = DTOR(m_rotationalVel * m_rotSensitivity);
}
if (p_und != NULL && (*p_und)[1] < 0.0f) {
if (p_up != NULL && (*p_up)[1] < 0.0f) {
delta_rad = -delta_rad;
}
@ -389,7 +389,7 @@ MxBool LegoNavController::CalculateNewPosDir(
changed = TRUE;
}
if (m_unk0x5d) {
if (m_keyPressed) {
float rot_mat[3][3];
Mx3DPointFloat delta_pos, new_pos, new_dir;
@ -402,20 +402,20 @@ MxBool LegoNavController::CalculateNewPosDir(
SET3(new_dir, p_curDir);
}
if (m_unk0x64 != 0.0f) {
delta_pos[0] = new_dir[0] * m_unk0x64;
delta_pos[1] = new_dir[1] * m_unk0x64;
delta_pos[2] = new_dir[2] * m_unk0x64;
if (m_additionalScale != 0.0f) {
delta_pos[0] = new_dir[0] * m_additionalScale;
delta_pos[1] = new_dir[1] * m_additionalScale;
delta_pos[2] = new_dir[2] * m_additionalScale;
}
else {
FILLVEC3(delta_pos, 0.0f);
}
delta_pos[1] += m_unk0x60;
delta_pos[1] += m_additionalHeightOffset;
VPV3(p_newPos, new_pos, delta_pos);
if (m_unk0x68 != 0.0f) {
float delta_rad = DTOR(m_unk0x68);
if (m_additionalRotationY != 0.0f) {
float delta_rad = DTOR(m_additionalRotationY);
IDENTMAT3(rot_mat);
rot_mat[0][0] = rot_mat[2][2] = cos(delta_rad);
rot_mat[0][2] = rot_mat[2][0] = sin(delta_rad);
@ -426,8 +426,8 @@ MxBool LegoNavController::CalculateNewPosDir(
SET3(p_newDir, new_dir);
}
m_unk0x60 = m_unk0x64 = m_unk0x68 = 0.0f;
m_unk0x5d = FALSE;
m_additionalHeightOffset = m_additionalScale = m_additionalRotationY = 0.0f;
m_keyPressed = FALSE;
changed = TRUE;
}
@ -523,7 +523,7 @@ MxS32 LegoNavController::GetNumLocations()
}
// FUNCTION: LEGO1 0x10055750
MxResult LegoNavController::ProcessJoystickInput(MxBool& p_und)
MxResult LegoNavController::ProcessJoystickInput(MxBool& p_rotatedY)
{
LegoOmni* instance = LegoOmni::GetInstance();
@ -556,7 +556,7 @@ MxResult LegoNavController::ProcessJoystickInput(MxBool& p_und)
if (world && world->GetCameraController()) {
world->GetCameraController()->RotateY(DTOR(povPosition));
p_und = TRUE;
p_rotatedY = TRUE;
}
}
@ -654,7 +654,7 @@ MxResult LegoNavController::ProcessKeyboardInput()
MxLong LegoNavController::Notify(MxParam& p_param)
{
if (((MxNotificationParam&) p_param).GetNotification() == c_notificationKeyPress) {
m_unk0x5d = TRUE;
m_keyPressed = TRUE;
SDL_Keycode originKey = ((LegoEventNotificationParam&) p_param).GetKey();
SDL_Keycode key = originKey;
@ -810,7 +810,7 @@ MxLong LegoNavController::Notify(MxParam& p_param)
g_fpsEnabled = TRUE;
}
default:
m_unk0x5d = FALSE;
m_keyPressed = FALSE;
break;
case SDLK_0:
case SDLK_1:
@ -978,7 +978,7 @@ MxLong LegoNavController::Notify(MxParam& p_param)
g_locationCalcStep = 1;
break;
case SDLK_D:
m_unk0x60 = -1.0;
m_additionalHeightOffset = -1.0;
break;
case SDLK_F:
RealtimeView::SetUserMaxLOD(0.0);
@ -1044,7 +1044,7 @@ MxLong LegoNavController::Notify(MxParam& p_param)
BackgroundAudioManager()->Enable(g_enableMusic);
break;
case SDLK_U:
m_unk0x60 = 1.0;
m_additionalHeightOffset = 1.0;
break;
case SDLK_V:
if (g_nextAnimation > 0 && g_animationCalcStep == 0) {

View File

@ -122,8 +122,8 @@ void LegoWorld::Destroy(MxBool p_fromDestructor)
if (presenter->IsA("LegoLocomotionAnimPresenter")) {
LegoLocomotionAnimPresenter* animPresenter = (LegoLocomotionAnimPresenter*) presenter;
animPresenter->DecrementUnknown0xd4();
if (animPresenter->GetUnknown0xd4() == 0) {
animPresenter->DecrementWorldRefCounter();
if (animPresenter->GetWorldRefCounter() == 0) {
ApplyMask(action, MxDSAction::c_world, FALSE);
presenter->EndAction();
}
@ -363,7 +363,7 @@ void LegoWorld::AddPresenterIfInRange(LegoAnimPresenter* p_presenter)
LegoPathController* controller;
while (cursor.Next(controller)) {
controller->FUN_100468f0(p_presenter);
controller->AddPresenterIfInRange(p_presenter);
}
}
@ -382,7 +382,7 @@ void LegoWorld::RemovePresenterFromBoundaries(LegoAnimPresenter* p_presenter)
// FUNCTION: LEGO1 0x1001ff80
void LegoWorld::AddPath(LegoPathController* p_controller)
{
p_controller->FUN_10046bb0(this);
p_controller->SetWorld(this);
m_pathControllerList.Append(p_controller);
}
@ -416,7 +416,7 @@ MxResult LegoWorld::GetCurrPathInfo(LegoPathBoundary** p_boundaries, MxS32& p_nu
return FAILURE;
}
return controller->FUN_10046b30(*p_boundaries, p_numL);
return controller->GetBoundaries(*p_boundaries, p_numL);
}
// FUNCTION: LEGO1 0x10020220

View File

@ -404,9 +404,9 @@ MxResult LegoWorldPresenter::LoadWorldModel(ModelDbModel& p_model, SDL_IOStream*
}
// FUNCTION: LEGO1 0x10067a70
void LegoWorldPresenter::VTable0x60(MxPresenter* p_presenter)
void LegoWorldPresenter::AdvanceSerialAction(MxPresenter* p_presenter)
{
MxCompositePresenter::VTable0x60(p_presenter);
MxCompositePresenter::AdvanceSerialAction(p_presenter);
MxDSAction* action = p_presenter->GetAction();
if (action->GetDuration() != -1 && (action->GetFlags() & MxDSAction::c_looping) == 0) {

View File

@ -63,10 +63,10 @@ MxResult LegoAnimActor::GetTimeInCycle(float& p_timeInCycle)
}
// FUNCTION: LEGO1 0x1001c240
void LegoAnimActor::VTable0x74(Matrix4& p_transform)
void LegoAnimActor::ApplyTransform(Matrix4& p_transform)
{
float timeInCycle;
LegoPathActor::VTable0x74(p_transform);
LegoPathActor::ApplyTransform(p_transform);
if (m_curAnim >= 0) {
GetTimeInCycle(timeInCycle);
@ -80,19 +80,19 @@ void LegoAnimActor::Animate(float p_time)
{
assert(m_roi);
if (m_lastTime == 0) {
m_lastTime = p_time - 1.0f;
if (m_transformTime == 0) {
m_transformTime = p_time - 1.0f;
}
if (m_actorState == c_initial && !m_userNavFlag && m_worldSpeed <= 0) {
if (m_curAnim >= 0) {
MxMatrix transform(m_unk0xec);
MxMatrix transform(m_local2World);
float timeInCycle;
GetTimeInCycle(timeInCycle);
AnimateWithTransform(timeInCycle, transform);
}
m_lastTime = m_actorTime = p_time;
m_transformTime = m_actorTime = p_time;
}
else {
LegoPathActor::Animate(p_time);
@ -109,7 +109,7 @@ MxResult LegoAnimActor::AnimateWithTransform(float p_time, Matrix4& p_transform)
LegoROI** roiMap = m_animMaps[m_curAnim]->m_roiMap;
MxU32 numROIs = m_animMaps[m_curAnim]->m_numROIs;
if (!m_boundary->GetFlag0x10()) {
if (!m_boundary->GetVisibility()) {
MxU32 i;
m_roi->SetVisibility(FALSE);
@ -244,7 +244,7 @@ void LegoAnimActor::ParseAction(char* p_extra)
token = strtok(NULL, g_parseExtraTokens);
if (token) {
p->FUN_1006d680(this, atof(token));
p->CreateROIAndBuildMap(this, atof(token));
}
}

View File

@ -12,7 +12,7 @@
DECOMP_SIZE_ASSERT(LegoExtraActor, 0x1dc)
// GLOBAL: LEGO1 0x100f31d0
LegoWorld* g_unk0x100f31d0 = NULL;
LegoWorld* g_reassemblyAnimWorld = NULL;
// GLOBAL: LEGO1 0x100f31d4
LegoLocomotionAnimPresenter* m_assAnimP = NULL;
@ -21,7 +21,7 @@ LegoLocomotionAnimPresenter* m_assAnimP = NULL;
LegoLocomotionAnimPresenter* m_disAnimP = NULL;
// GLOBAL: LEGO1 0x100f31dc
MxS32 g_unk0x100f31dc = 0;
MxS32 g_hitCounter = 0;
// GLOBAL: LEGO1 0x10104c18
Mx3DPointFloat g_unk0x10104c18 = Mx3DPointFloat(0.0f, 2.5f, 0.0f);
@ -32,12 +32,12 @@ LegoExtraActor::LegoExtraActor()
{
m_lastPathStruct = 0.0f;
m_scheduledTime = 0;
m_unk0x0c = 0;
m_unk0x0e = 0;
m_whichAnim = 0;
m_pathWalkingMode = 0;
m_animationAtCurrentBoundary = FALSE;
m_reassemblyAnimation = e_none;
m_assAnim = NULL;
m_disAnim = NULL;
m_unk0x15 = 0;
m_hitBlockCounter = 0;
}
// FUNCTION: LEGO1 0x1002a6b0
@ -48,19 +48,19 @@ LegoExtraActor::~LegoExtraActor()
}
// FUNCTION: LEGO1 0x1002a720
MxU32 LegoExtraActor::VTable0x90(float p_time, Matrix4& p_transform)
MxU32 LegoExtraActor::StepState(float p_time, Matrix4& p_transform)
{
switch (m_actorState & c_maxState) {
case c_initial:
case c_one:
case c_ready:
return TRUE;
case c_two:
case c_hit:
m_scheduledTime = p_time + 2000.0f;
m_actorState = c_three;
m_actorTime += (p_time - m_lastTime) * m_worldSpeed;
m_lastTime = p_time;
m_actorState = c_hitAnimation;
m_actorTime += (p_time - m_transformTime) * m_worldSpeed;
m_transformTime = p_time;
return FALSE;
case c_three: {
case c_hitAnimation: {
Vector3 positionRef(p_transform[3]);
p_transform = m_roi->GetLocal2World();
@ -89,9 +89,9 @@ MxU32 LegoExtraActor::VTable0x90(float p_time, Matrix4& p_transform)
}
positionRef = position;
m_actorTime += (p_time - m_lastTime) * m_worldSpeed;
m_lastTime = p_time;
VTable0x74(p_transform);
m_actorTime += (p_time - m_transformTime) * m_worldSpeed;
m_transformTime = p_time;
ApplyTransform(p_transform);
return FALSE;
}
else {
@ -109,32 +109,32 @@ MxU32 LegoExtraActor::VTable0x90(float p_time, Matrix4& p_transform)
}
// FUNCTION: LEGO1 0x1002aa90
void LegoExtraActor::VTable0xa4(MxBool& p_und1, MxS32& p_und2)
void LegoExtraActor::GetWalkingBehavior(MxBool& p_countCounterclockWise, MxS32& p_selectedEdgeIndex)
{
switch (m_unk0x0c) {
switch (m_pathWalkingMode) {
case 1:
p_und1 = TRUE;
p_und2 = 1;
p_countCounterclockWise = TRUE;
p_selectedEdgeIndex = 1;
break;
case 2:
p_und1 = FALSE;
p_und2 = 1;
p_countCounterclockWise = FALSE;
p_selectedEdgeIndex = 1;
break;
default:
p_und1 = TRUE;
p_und2 = 1 + SDL_rand(p_und2);
p_countCounterclockWise = TRUE;
p_selectedEdgeIndex = 1 + SDL_rand(p_selectedEdgeIndex);
break;
}
}
// FUNCTION: LEGO1 0x1002aae0
MxResult LegoExtraActor::FUN_1002aae0()
MxResult LegoExtraActor::SwitchDirection()
{
LegoPathBoundary* oldEdge = m_boundary;
Vector3 rightRef(m_unk0xec[0]);
Vector3 upRef(m_unk0xec[1]);
Vector3 dirRef(m_unk0xec[2]);
Vector3 positionRef(m_unk0xec[3]);
Vector3 rightRef(m_local2World[0]);
Vector3 upRef(m_local2World[1]);
Vector3 dirRef(m_local2World[2]);
Vector3 positionRef(m_local2World[3]);
dirRef *= -1.0f;
rightRef.EqualsCross(upRef, dirRef);
@ -150,23 +150,23 @@ MxResult LegoExtraActor::FUN_1002aae0()
m_boundary = oldEdge;
}
LegoPathActor::VTable0x9c();
LegoPathActor::CalculateSpline();
return SUCCESS;
}
inline void LegoExtraActor::FUN_1002ad8a()
inline void LegoExtraActor::InitializeReassemblyAnim()
{
LegoWorld* w = CurrentWorld();
if (g_unk0x100f31d0 != w) {
g_unk0x100f31d0 = w;
if (g_reassemblyAnimWorld != w) {
g_reassemblyAnimWorld = w;
m_assAnimP = (LegoLocomotionAnimPresenter*) w->Find("LegoAnimPresenter", "BNsAss01");
m_disAnimP = (LegoLocomotionAnimPresenter*) w->Find("LegoAnimPresenter", "BNsDis01");
}
if (!m_assAnim) {
MxS32 index = 0;
m_assAnimP->FUN_1006d680(this, -20.0f);
m_assAnimP->CreateROIAndBuildMap(this, -20.0f);
for (MxS32 i = 0; i < m_animMaps.size(); i++) {
if (m_animMaps[i]->GetWorldSpeed() == -20.0f) {
@ -178,7 +178,7 @@ inline void LegoExtraActor::FUN_1002ad8a()
if (!m_disAnim) {
MxS32 index = 0;
m_disAnimP->FUN_1006d680(this, -21.0f);
m_disAnimP->CreateROIAndBuildMap(this, -21.0f);
for (MxS32 i = 0; i < m_animMaps.size(); i++) {
if (m_animMaps[i]->GetWorldSpeed() == -21.0f) {
@ -198,26 +198,26 @@ MxResult LegoExtraActor::HitActor(LegoPathActor* p_actor, MxBool p_bool)
}
if (p_bool) {
if (m_unk0x15 != 0) {
if (m_hitBlockCounter != 0) {
return FAILURE;
}
m_unk0x15 = 100;
FUN_1002aae0();
m_hitBlockCounter = 100;
SwitchDirection();
}
else {
MxU32 b = FALSE;
if (++g_unk0x100f31dc % 2 == 0) {
MxMatrix matrix(p_actor->GetROI()->GetLocal2World());
MxMatrix matrix2(m_roi->GetLocal2World());
if (++g_hitCounter % 2 == 0) {
MxMatrix otherActorLocal(p_actor->GetROI()->GetLocal2World());
MxMatrix local(m_roi->GetLocal2World());
m_unk0x18 = matrix2;
Vector3 positionRef(matrix2[3]);
Mx3DPointFloat dir(matrix[2]);
m_localBeforeHit = local;
Vector3 positionRef(local[3]);
Mx3DPointFloat otherActorDir(otherActorLocal[2]);
dir *= 2.0f;
positionRef += dir;
otherActorDir *= 2.0f;
positionRef += otherActorDir;
for (MxS32 i = 0; i < m_boundary->GetNumEdges(); i++) {
Mx4DPointFloat* normal = m_boundary->GetEdgeNormal(i);
@ -229,9 +229,9 @@ MxResult LegoExtraActor::HitActor(LegoPathActor* p_actor, MxBool p_bool)
}
if (!b) {
m_roi->SetLocal2World(matrix2);
m_roi->SetLocal2World(local);
m_roi->WrappedUpdateWorldData();
FUN_1002ad8a();
InitializeReassemblyAnim();
assert(m_roi);
assert(SoundManager()->GetCacheSoundManager());
SoundManager()->GetCacheSoundManager()->Play("crash5", m_roi->GetName(), FALSE);
@ -242,8 +242,8 @@ MxResult LegoExtraActor::HitActor(LegoPathActor* p_actor, MxBool p_bool)
m_prevWorldSpeed = GetWorldSpeed();
VTable0xc4();
SetWorldSpeed(0);
m_whichAnim = 1;
SetActorState(c_one | c_noCollide);
m_reassemblyAnimation = e_disassemble;
SetActorState(c_ready | c_noCollide);
}
}
@ -255,7 +255,7 @@ MxResult LegoExtraActor::HitActor(LegoPathActor* p_actor, MxBool p_bool)
EmitGameEvent(e_hitActor);
}
VTable0xc4();
SetActorState(c_two | c_noCollide);
SetActorState(c_hit | c_noCollide);
Mx3DPointFloat dir = p_actor->GetWorldDirection();
MxMatrix matrix3 = MxMatrix(roi->GetLocal2World());
Vector3 positionRef(matrix3[3]);
@ -278,25 +278,25 @@ MxResult LegoExtraActor::HitActor(LegoPathActor* p_actor, MxBool p_bool)
}
// FUNCTION: LEGO1 0x1002b290
MxResult LegoExtraActor::VTable0x9c()
MxResult LegoExtraActor::CalculateSpline()
{
LegoPathBoundary* oldBoundary = m_boundary;
MxResult result = LegoPathActor::VTable0x9c();
MxResult result = LegoPathActor::CalculateSpline();
if (m_boundary != oldBoundary) {
MxU32 b = FALSE;
MxU32 foundAnimation = FALSE;
LegoAnimPresenterSet& presenters = m_boundary->GetPresenters();
for (LegoAnimPresenterSet::iterator it = presenters.begin(); it != presenters.end(); it++) {
MxU32 roiMapSize;
if ((*it)->GetROIMap(roiMapSize)) {
b = TRUE;
foundAnimation = TRUE;
break;
}
}
if (b) {
m_unk0x0e = 1;
if (foundAnimation) {
m_animationAtCurrentBoundary = TRUE;
m_prevWorldSpeed = GetWorldSpeed();
SetWorldSpeed(0);
}
@ -308,21 +308,21 @@ MxResult LegoExtraActor::VTable0x9c()
// FUNCTION: LEGO1 0x1002b370
void LegoExtraActor::Restart()
{
if (m_unk0x0e != 0) {
MxU32 b = FALSE;
if (m_animationAtCurrentBoundary != 0) {
MxU32 foundAnimation = FALSE;
LegoAnimPresenterSet& presenters = m_boundary->GetPresenters();
for (LegoAnimPresenterSet::iterator it = presenters.begin(); it != presenters.end(); it++) {
MxU32 roiMapSize;
if ((*it)->GetROIMap(roiMapSize)) {
b = TRUE;
foundAnimation = TRUE;
break;
}
}
if (!b) {
if (!foundAnimation) {
SetWorldSpeed(m_prevWorldSpeed);
m_unk0x0e = 0;
m_animationAtCurrentBoundary = FALSE;
}
}
}
@ -332,14 +332,14 @@ void LegoExtraActor::Animate(float p_time)
{
LegoAnimActorStruct* laas = NULL;
switch (m_whichAnim) {
case 0:
switch (m_reassemblyAnimation) {
case e_none:
LegoAnimActor::Animate(p_time);
break;
case 1:
case e_disassemble:
if (m_scheduledTime < p_time) {
m_whichAnim = 2;
m_actorState = c_one | c_noCollide;
m_reassemblyAnimation = e_assemble;
m_actorState = c_ready | c_noCollide;
m_scheduledTime = m_assAnim->GetDuration() + p_time;
break;
}
@ -347,13 +347,13 @@ void LegoExtraActor::Animate(float p_time)
laas = m_disAnim;
break;
}
case 2:
case e_assemble:
if (m_scheduledTime < p_time) {
m_whichAnim = 0;
m_reassemblyAnimation = e_none;
m_actorState = c_initial;
SetWorldSpeed(m_prevWorldSpeed);
m_roi->SetLocal2World(m_unk0x18);
m_lastTime = p_time;
m_roi->SetLocal2World(m_localBeforeHit);
m_transformTime = p_time;
break;
}
else {
@ -385,10 +385,10 @@ void LegoExtraActor::Animate(float p_time)
}
// FUNCTION: LEGO1 0x1002b5d0
void LegoExtraActor::VTable0x74(Matrix4& p_transform)
void LegoExtraActor::ApplyTransform(Matrix4& p_transform)
{
if (m_whichAnim == 0) {
LegoAnimActor::VTable0x74(p_transform);
if (m_reassemblyAnimation == e_none) {
LegoAnimActor::ApplyTransform(p_transform);
}
}
@ -415,32 +415,32 @@ void LegoExtraActor::VTable0xc4()
if (b) {
float duration = m_animMaps[m_curAnim]->GetDuration();
MxMatrix matrix(m_unk0xec);
MxMatrix matrix(m_local2World);
LegoAnimActor::AnimateWithTransform(duration, matrix);
}
}
}
// FUNCTION: LEGO1 0x1002b6f0
MxS32 LegoExtraActor::VTable0x68(Vector3& p_point1, Vector3& p_point2, Vector3& p_point3)
MxS32 LegoExtraActor::CheckIntersections(Vector3& p_rayOrigin, Vector3& p_rayEnd, Vector3& p_intersectionPoint)
{
return LegoPathActor::VTable0x68(p_point1, p_point2, p_point3);
return LegoPathActor::CheckIntersections(p_rayOrigin, p_rayEnd, p_intersectionPoint);
}
// FUNCTION: LEGO1 0x1002b980
inline MxU32 LegoExtraActor::VTable0x6c(
inline MxU32 LegoExtraActor::CheckPresenterAndActorIntersections(
LegoPathBoundary* p_boundary,
Vector3& p_v1,
Vector3& p_v2,
float p_f1,
float p_f2,
Vector3& p_v3
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint
)
{
LegoAnimPresenterSet& presenters = p_boundary->GetPresenters();
for (LegoAnimPresenterSet::iterator itap = presenters.begin(); itap != presenters.end(); itap++) {
if ((*itap)->VTable0x94(p_v1, p_v2, p_f1, p_f2, p_v3)) {
if ((*itap)->Intersect(p_rayOrigin, p_rayDirection, p_rayLength, p_radius, p_intersectionPoint)) {
return 1;
}
}
@ -459,14 +459,14 @@ inline MxU32 LegoExtraActor::VTable0x6c(
if (actor->GetUserNavFlag()) {
MxMatrix local2world = roi->GetLocal2World();
Vector3 local60(local2world[3]);
Mx3DPointFloat local54(p_v1);
Mx3DPointFloat local54(p_rayOrigin);
local54 -= local60;
float local1c = p_v2.Dot(p_v2, p_v2);
float local24 = p_v2.Dot(p_v2, local54) * 2.0f;
float local1c = p_rayDirection.Dot(p_rayDirection, p_rayDirection);
float local24 = p_rayDirection.Dot(p_rayDirection, local54) * 2.0f;
float local20 = local54.Dot(local54, local54);
if (m_unk0x15 != 0 && local20 < 10.0f) {
if (m_hitBlockCounter != 0 && local20 < 10.0f) {
return 0;
}
@ -493,9 +493,10 @@ inline MxU32 LegoExtraActor::VTable0x6c(
local1cX = local40;
}
if ((local20X >= 0.0f && local20X <= p_f1) || (local1cX >= 0.0f && local1cX <= p_f1) ||
(local20X <= -0.01 && p_f1 + 0.01 <= local1cX)) {
p_v3 = p_v1;
if ((local20X >= 0.0f && local20X <= p_rayLength) ||
(local1cX >= 0.0f && local1cX <= p_rayLength) ||
(local20X <= -0.01 && p_rayLength + 0.01 <= local1cX)) {
p_intersectionPoint = p_rayOrigin;
if (HitActor(actor, TRUE) < 0) {
return 0;
@ -508,7 +509,14 @@ inline MxU32 LegoExtraActor::VTable0x6c(
}
}
else {
if (roi->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) {
if (roi->Intersect(
p_rayOrigin,
p_rayDirection,
p_rayLength,
p_radius,
p_intersectionPoint,
m_collideBox && actor->GetCollideBox()
)) {
if (HitActor(actor, TRUE) < 0) {
return 0;
}
@ -522,8 +530,8 @@ inline MxU32 LegoExtraActor::VTable0x6c(
}
}
if (m_unk0x15 != 0) {
m_unk0x15--;
if (m_hitBlockCounter != 0) {
m_hitBlockCounter--;
}
return 0;

View File

@ -45,18 +45,18 @@ LegoPathActor::LegoPathActor()
{
m_boundary = NULL;
m_actorTime = 0;
m_lastTime = 0;
m_unk0x7c = 0;
m_transformTime = 0;
m_traveledDistance = 0;
m_userNavFlag = FALSE;
m_actorState = c_initial;
m_grec = NULL;
m_pathController = NULL;
m_collideBox = FALSE;
m_unk0x148 = 0;
m_unk0x14c = 0;
m_unk0x140 = 0.0099999999f;
m_unk0x144 = 0.8f;
m_unk0x150 = 2.0f;
m_canRotate = 0;
m_lastRotationAngle = 0;
m_wallHitDirectionFactor = 0.0099999999f;
m_wallHitDampening = 0.8f;
m_linearRotationRatio = 2.0f;
}
// FUNCTION: LEGO1 0x1002d820
@ -70,19 +70,24 @@ LegoPathActor::~LegoPathActor()
// FUNCTION: LEGO1 0x1002d8d0
// FUNCTION: BETA10 0x100ae8cd
MxResult LegoPathActor::VTable0x80(const Vector3& p_point1, Vector3& p_point2, Vector3& p_point3, Vector3& p_point4)
MxResult LegoPathActor::SetSpline(
const Vector3& p_start,
Vector3& p_tangentAtStart,
Vector3& p_end,
Vector3& p_tangentAtEnd
)
{
Mx3DPointFloat p1, p2, p3;
Mx3DPointFloat length, tangentAtStart, tangentAtEnd;
p1 = p_point3;
p1 -= p_point1;
m_BADuration = p1.LenSquared();
length = p_end;
length -= p_start;
m_BADuration = length.LenSquared();
if (m_BADuration > 0.0f) {
m_BADuration = sqrtf(m_BADuration);
p2 = p_point2;
p3 = p_point4;
m_unk0x8c.FUN_1009a140(p_point1, p2, p_point3, p3);
tangentAtStart = p_tangentAtStart;
tangentAtEnd = p_tangentAtEnd;
m_spline.SetSpline(p_start, tangentAtStart, p_end, tangentAtEnd);
m_BADuration /= 0.001;
return SUCCESS;
}
@ -94,7 +99,7 @@ MxResult LegoPathActor::VTable0x80(const Vector3& p_point1, Vector3& p_point2, V
// FUNCTION: LEGO1 0x1002d9c0
// FUNCTION: BETA10 0x100ae9da
MxResult LegoPathActor::VTable0x88(
MxResult LegoPathActor::SetTransformAndDestinationFromEdge(
LegoPathBoundary* p_boundary,
float p_time,
LegoEdge& p_srcEdge,
@ -108,29 +113,29 @@ MxResult LegoPathActor::VTable0x88(
Vector3* v3 = p_destEdge.CWVertex(*p_boundary);
Vector3* v4 = p_destEdge.CCWVertex(*p_boundary);
Mx3DPointFloat p1, p2, p3, p4, p5;
Mx3DPointFloat start, end, destNormal, startDirection, endDirection;
p1 = *v2;
p1 -= *v1;
p1 *= p_srcScale;
p1 += *v1;
start = *v2;
start -= *v1;
start *= p_srcScale;
start += *v1;
p2 = *v4;
p2 -= *v3;
p2 *= p_destScale;
p2 += *v3;
end = *v4;
end -= *v3;
end *= p_destScale;
end += *v3;
m_boundary = p_boundary;
m_destEdge = &p_destEdge;
m_unk0xe4 = p_destScale;
m_unk0x7c = 0;
m_lastTime = p_time;
m_destScale = p_destScale;
m_traveledDistance = 0;
m_transformTime = p_time;
m_actorTime = p_time;
p_destEdge.GetFaceNormal(*p_boundary, p3);
p_destEdge.GetFaceNormal(*p_boundary, destNormal);
p4 = p2;
p4 -= p1;
p4.Unitize();
startDirection = end;
startDirection -= start;
startDirection.Unitize();
MxMatrix matrix;
Vector3 pos(matrix[3]);
@ -139,8 +144,8 @@ MxResult LegoPathActor::VTable0x88(
Vector3 right(matrix[0]);
matrix.SetIdentity();
pos = p1;
dir = p4;
pos = start;
dir = startDirection;
up = *m_boundary->GetUp();
if (!m_cameraFlag || !m_userNavFlag) {
@ -151,10 +156,10 @@ MxResult LegoPathActor::VTable0x88(
m_roi->UpdateTransformationRelativeToParent(matrix);
if (!m_cameraFlag || !m_userNavFlag) {
p5.EqualsCross(*p_boundary->GetUp(), p3);
p5.Unitize();
endDirection.EqualsCross(*p_boundary->GetUp(), destNormal);
endDirection.Unitize();
if (VTable0x80(p1, p4, p2, p5) == SUCCESS) {
if (SetSpline(start, startDirection, end, endDirection) == SUCCESS) {
m_boundary->AddActor(this);
}
else {
@ -166,17 +171,17 @@ MxResult LegoPathActor::VTable0x88(
TransformPointOfView();
}
m_unk0xec = m_roi->GetLocal2World();
m_local2World = m_roi->GetLocal2World();
return SUCCESS;
}
// FUNCTION: LEGO1 0x1002de10
// FUNCTION: BETA10 0x100aee61
MxResult LegoPathActor::VTable0x84(
MxResult LegoPathActor::SetTransformAndDestinationFromPoints(
LegoPathBoundary* p_boundary,
float p_time,
Vector3& p_p1,
Vector3& p_p4,
Vector3& p_start,
Vector3& p_direction,
LegoOrientedEdge* p_destEdge,
float p_destScale
)
@ -188,20 +193,20 @@ MxResult LegoPathActor::VTable0x84(
assert(v3 && v4);
Mx3DPointFloat p2, p3, p5;
Mx3DPointFloat end, destNormal, endDirection;
p2 = *v4;
p2 -= *v3;
p2 *= p_destScale;
p2 += *v3;
end = *v4;
end -= *v3;
end *= p_destScale;
end += *v3;
m_boundary = p_boundary;
m_destEdge = p_destEdge;
m_unk0xe4 = p_destScale;
m_unk0x7c = 0;
m_lastTime = p_time;
m_destScale = p_destScale;
m_traveledDistance = 0;
m_transformTime = p_time;
m_actorTime = p_time;
p_destEdge->GetFaceNormal(*p_boundary, p3);
p_destEdge->GetFaceNormal(*p_boundary, destNormal);
MxMatrix matrix;
Vector3 pos(matrix[3]);
@ -210,8 +215,8 @@ MxResult LegoPathActor::VTable0x84(
Vector3 right(matrix[0]);
matrix.SetIdentity();
pos = p_p1;
dir = p_p4;
pos = p_start;
dir = p_direction;
up = *m_boundary->GetUp();
if (!m_cameraFlag || !m_userNavFlag) {
@ -226,10 +231,10 @@ MxResult LegoPathActor::VTable0x84(
TransformPointOfView();
}
else {
p5.EqualsCross(*p_boundary->GetUp(), p3);
p5.Unitize();
endDirection.EqualsCross(*p_boundary->GetUp(), destNormal);
endDirection.Unitize();
if (VTable0x80(p_p1, p_p4, p2, p5) != SUCCESS) {
if (SetSpline(p_start, p_direction, end, endDirection) != SUCCESS) {
MxTrace("Warning: m_BADuration = %g, roi = %s\n", m_BADuration, m_roi->GetName());
return FAILURE;
}
@ -237,57 +242,59 @@ MxResult LegoPathActor::VTable0x84(
m_boundary->AddActor(this);
}
m_unk0xec = m_roi->GetLocal2World();
m_local2World = m_roi->GetLocal2World();
return SUCCESS;
}
// FUNCTION: LEGO1 0x1002e100
// FUNCTION: BETA10 0x100b0520
MxS32 LegoPathActor::VTable0x8c(float p_time, Matrix4& p_transform)
MxS32 LegoPathActor::CalculateTransform(float p_time, Matrix4& p_transform)
{
if (m_userNavFlag && m_actorState == c_initial) {
m_lastTime = p_time;
m_transformTime = p_time;
Mx3DPointFloat p1, p2, p3, p4, p5;
p5 = Vector3(m_roi->GetWorldDirection());
p4 = Vector3(m_roi->GetWorldPosition());
Mx3DPointFloat newDir, newPos, intersectionPoint, pos, dir;
dir = Vector3(m_roi->GetWorldDirection());
pos = Vector3(m_roi->GetWorldPosition());
LegoNavController* nav = NavController();
assert(nav);
m_worldSpeed = nav->GetLinearVel();
if (nav->CalculateNewPosDir(p4, p5, p2, p1, m_boundary->GetUp())) {
Mx3DPointFloat p6;
p6 = p2;
if (nav->CalculateNewPosDir(pos, dir, newPos, newDir, m_boundary->GetUp())) {
Mx3DPointFloat newPosCopy;
newPosCopy = newPos;
MxS32 result = 0;
m_unk0xe9 = m_boundary->Intersect(m_roi->GetWorldBoundingSphere().Radius(), p4, p2, p3, m_destEdge);
if (m_unk0xe9 == -1) {
m_finishedTravel =
m_boundary
->Intersect(m_roi->GetWorldBoundingSphere().Radius(), pos, newPos, intersectionPoint, m_destEdge);
if (m_finishedTravel == -1) {
MxTrace("Intersect returned -1\n");
return -1;
}
else {
if (m_unk0xe9 != 0) {
p2 = p3;
if (m_finishedTravel != FALSE) {
newPos = intersectionPoint;
}
}
result = VTable0x68(p4, p2, p3);
result = CheckIntersections(pos, newPos, intersectionPoint);
if (result > 0) {
p2 = p4;
m_unk0xe9 = 0;
newPos = pos;
m_finishedTravel = FALSE;
result = 0;
}
else {
m_boundary->CheckAndCallPathTriggers(p4, p2, this);
m_boundary->CheckAndCallPathTriggers(pos, newPos, this);
}
LegoPathBoundary* oldBoundary = m_boundary;
if (m_unk0xe9 != 0) {
VTable0x9c();
if (m_finishedTravel != FALSE) {
CalculateSpline();
if (m_boundary == oldBoundary) {
MxLong time = Timer()->GetTime();
@ -301,15 +308,15 @@ MxS32 LegoPathActor::VTable0x8c(float p_time, Matrix4& p_transform)
}
}
m_worldSpeed *= m_unk0x144;
m_worldSpeed *= m_wallHitDampening;
nav->SetLinearVel(m_worldSpeed);
Mx3DPointFloat p7(p2);
p7 -= p6;
Mx3DPointFloat newPosDelta(newPos);
newPosDelta -= newPosCopy;
if (p7.Unitize() == 0) {
float f = sqrt(p1.LenSquared()) * m_unk0x140;
p7 *= f;
p1 += p7;
if (newPosDelta.Unitize() == 0) {
float f = sqrt(newDir.LenSquared()) * m_wallHitDirectionFactor;
newPosDelta *= f;
newDir += newPosDelta;
}
}
}
@ -321,7 +328,7 @@ MxS32 LegoPathActor::VTable0x8c(float p_time, Matrix4& p_transform)
Vector3 dir(p_transform[2]);
Vector3 pos(p_transform[3]);
dir = p1;
dir = newDir;
up = *m_boundary->GetUp();
right.EqualsCross(up, dir);
@ -329,7 +336,7 @@ MxS32 LegoPathActor::VTable0x8c(float p_time, Matrix4& p_transform)
assert(res == 0);
dir.EqualsCross(right, up);
pos = p2;
pos = newPos;
return result;
}
else {
@ -337,47 +344,47 @@ MxS32 LegoPathActor::VTable0x8c(float p_time, Matrix4& p_transform)
}
}
else if (p_time >= 0 && m_worldSpeed > 0) {
float f = (m_BADuration - m_unk0x7c) / m_worldSpeed + m_lastTime;
float endTime = (m_BADuration - m_traveledDistance) / m_worldSpeed + m_transformTime;
if (f < p_time) {
m_unk0x7c = m_BADuration;
m_unk0xe9 = 1;
if (endTime < p_time) {
m_traveledDistance = m_BADuration;
m_finishedTravel = TRUE;
}
else {
f = p_time;
m_unk0x7c += (f - m_lastTime) * m_worldSpeed;
m_unk0xe9 = 0;
endTime = p_time;
m_traveledDistance += (endTime - m_transformTime) * m_worldSpeed;
m_finishedTravel = FALSE;
}
m_actorTime += (f - m_lastTime) * m_worldSpeed;
m_lastTime = f;
m_actorTime += (endTime - m_transformTime) * m_worldSpeed;
m_transformTime = endTime;
p_transform.SetIdentity();
LegoResult r;
if (m_userNavFlag) {
r = m_unk0x8c.FUN_1009a1e0(m_unk0x7c / m_BADuration, p_transform, *m_boundary->GetUp(), 0);
r = m_spline.Evaluate(m_traveledDistance / m_BADuration, p_transform, *m_boundary->GetUp(), FALSE);
}
else {
r = m_unk0x8c.FUN_1009a1e0(m_unk0x7c / m_BADuration, p_transform, *m_boundary->GetUp(), 1);
r = m_spline.Evaluate(m_traveledDistance / m_BADuration, p_transform, *m_boundary->GetUp(), TRUE);
}
assert(r == 0); // SUCCESS
Vector3 pos1(p_transform[3]);
Vector3 pos2(m_unk0xec[3]);
Vector3 end(p_transform[3]);
Vector3 origin(m_local2World[3]);
Mx3DPointFloat p1;
if (VTable0x68(pos2, pos1, p1) > 0) {
m_lastTime = p_time;
if (CheckIntersections(origin, end, p1) > 0) {
m_transformTime = p_time;
return 1;
}
else {
m_boundary->CheckAndCallPathTriggers(pos2, pos1, this);
pos2 = pos1;
m_boundary->CheckAndCallPathTriggers(origin, end, this);
origin = end;
}
if (m_unk0xe9 != 0) {
VTable0x9c();
if (m_finishedTravel != FALSE) {
CalculateSpline();
}
}
else {
@ -389,7 +396,7 @@ MxS32 LegoPathActor::VTable0x8c(float p_time, Matrix4& p_transform)
// FUNCTION: LEGO1 0x1002e740
// FUNCTION: BETA10 0x100b0f70
void LegoPathActor::VTable0x74(Matrix4& p_transform)
void LegoPathActor::ApplyTransform(Matrix4& p_transform)
{
if (m_userNavFlag) {
m_roi->WrappedSetLocal2WorldWithWorldDataUpdate(p_transform);
@ -410,69 +417,70 @@ void LegoPathActor::VTable0x74(Matrix4& p_transform)
void LegoPathActor::Animate(float p_time)
{
MxMatrix transform;
MxU32 b = FALSE;
MxU32 applyTransform = FALSE;
while (m_lastTime < p_time) {
if (m_actorState != c_initial && !VTable0x90(p_time, transform)) {
while (m_transformTime < p_time) {
if (m_actorState != c_initial && !StepState(p_time, transform)) {
return;
}
if (VTable0x8c(p_time, transform) != 0) {
if (CalculateTransform(p_time, transform) != 0) {
break;
}
m_unk0xec = transform;
b = TRUE;
m_local2World = transform;
applyTransform = TRUE;
if (m_unk0xe9 != 0) {
if (m_finishedTravel != FALSE) {
break;
}
}
if (m_userNavFlag && m_unk0x148) {
if (m_userNavFlag && m_canRotate) {
LegoNavController* nav = NavController();
float vel = (nav->GetLinearVel() > 0)
? -(nav->GetRotationalVel() / (nav->GetMaxLinearVel() * m_unk0x150) * nav->GetLinearVel())
: 0;
float vel =
(nav->GetLinearVel() > 0)
? -(nav->GetRotationalVel() / (nav->GetMaxLinearVel() * m_linearRotationRatio) * nav->GetLinearVel())
: 0;
if ((MxS32) vel != m_unk0x14c) {
m_unk0x14c = vel;
if ((MxS32) vel != m_lastRotationAngle) {
m_lastRotationAngle = vel;
LegoWorld* world = CurrentWorld();
if (world) {
world->GetCameraController()->RotateZ(DTOR(m_unk0x14c));
world->GetCameraController()->RotateZ(DTOR(m_lastRotationAngle));
}
}
}
if (b) {
VTable0x74(transform);
if (applyTransform) {
ApplyTransform(transform);
}
}
// FUNCTION: LEGO1 0x1002e8b0
// FUNCTION: BETA10 0x100af2f7
void LegoPathActor::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoOrientedEdge*& p_edge, float& p_unk0xe4)
void LegoPathActor::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoOrientedEdge*& p_edge, float& p_scale)
{
assert(m_boundary);
m_boundary->SwitchBoundary(this, p_boundary, p_edge, p_unk0xe4);
m_boundary->SwitchBoundary(this, p_boundary, p_edge, p_scale);
}
// FUNCTION: LEGO1 0x1002e8d0
// FUNCTION: BETA10 0x100b1010
MxU32 LegoPathActor::VTable0x6c(
MxU32 LegoPathActor::CheckPresenterAndActorIntersections(
LegoPathBoundary* p_boundary,
Vector3& p_v1,
Vector3& p_v2,
float p_f1,
float p_f2,
Vector3& p_v3
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint
)
{
LegoAnimPresenterSet& presenters = p_boundary->GetPresenters();
for (LegoAnimPresenterSet::iterator itap = presenters.begin(); itap != presenters.end(); itap++) {
if ((*itap)->VTable0x94(p_v1, p_v2, p_f1, p_f2, p_v3)) {
if ((*itap)->Intersect(p_rayOrigin, p_rayDirection, p_rayLength, p_radius, p_intersectionPoint)) {
return 1;
}
}
@ -488,7 +496,14 @@ MxU32 LegoPathActor::VTable0x6c(
LegoROI* roi = actor->GetROI();
if (roi != NULL && (roi->GetVisibility() || actor->GetCameraFlag())) {
if (roi->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->m_collideBox)) {
if (roi->Intersect(
p_rayOrigin,
p_rayDirection,
p_rayLength,
p_radius,
p_intersectionPoint,
m_collideBox && actor->m_collideBox
)) {
HitActor(actor, TRUE);
actor->HitActor(this, FALSE);
return 2;
@ -501,26 +516,33 @@ MxU32 LegoPathActor::VTable0x6c(
return 0;
}
inline MxU32 LegoPathActor::FUN_1002edd0(
list<LegoPathBoundary*>& p_boundaries,
inline MxU32 LegoPathActor::CheckIntersectionBothFaces(
list<LegoPathBoundary*>& p_checkedBoundaries,
LegoPathBoundary* p_boundary,
Vector3& p_v1,
Vector3& p_v2,
float p_f1,
float p_f2,
Vector3& p_v3,
MxS32 p_und
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint,
MxS32 p_depth
)
{
MxU32 result = VTable0x6c(p_boundary, p_v1, p_v2, p_f1, p_f2, p_v3);
MxU32 result = CheckPresenterAndActorIntersections(
p_boundary,
p_rayOrigin,
p_rayDirection,
p_rayLength,
p_radius,
p_intersectionPoint
);
if (result != 0) {
return result;
}
p_boundaries.push_back(p_boundary);
p_checkedBoundaries.push_back(p_boundary);
if (p_und >= 2) {
if (p_depth >= 2) {
return 0;
}
@ -532,14 +554,23 @@ inline MxU32 LegoPathActor::FUN_1002edd0(
if (boundary != NULL) {
list<LegoPathBoundary*>::const_iterator it;
for (it = p_boundaries.begin(); !(it == p_boundaries.end()); it++) {
for (it = p_checkedBoundaries.begin(); !(it == p_checkedBoundaries.end()); it++) {
if ((*it) == boundary) {
break;
}
}
if (it == p_boundaries.end()) {
result = FUN_1002edd0(p_boundaries, boundary, p_v1, p_v2, p_f1, p_f2, p_v3, p_und + 1);
if (it == p_checkedBoundaries.end()) {
result = CheckIntersectionBothFaces(
p_checkedBoundaries,
boundary,
p_rayOrigin,
p_rayDirection,
p_rayLength,
p_radius,
p_intersectionPoint,
p_depth + 1
);
if (result != 0) {
return result;
@ -553,26 +584,35 @@ inline MxU32 LegoPathActor::FUN_1002edd0(
// FUNCTION: LEGO1 0x1002ebe0
// FUNCTION: BETA10 0x100af35e
MxS32 LegoPathActor::VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3)
MxS32 LegoPathActor::CheckIntersections(Vector3& p_rayOrigin, Vector3& p_rayEnd, Vector3& p_intersectionPoint)
{
assert(m_boundary && m_roi);
Mx3DPointFloat v2(p_v2);
v2 -= p_v1;
Mx3DPointFloat rayDirection(p_rayEnd);
rayDirection -= p_rayOrigin;
float len = v2.LenSquared();
float len = rayDirection.LenSquared();
if (len <= 0.001) {
return 0;
}
len = sqrt((double) len);
v2 /= len;
rayDirection /= len;
float radius = m_roi->GetWorldBoundingSphere().Radius();
list<LegoPathBoundary*> boundaries;
return FUN_1002edd0(boundaries, m_boundary, p_v1, v2, len, radius, p_v3, 0);
return CheckIntersectionBothFaces(
boundaries,
m_boundary,
p_rayOrigin,
rayDirection,
len,
radius,
p_intersectionPoint,
0
);
}
// FUNCTION: LEGO1 0x1002f020
@ -623,20 +663,21 @@ void LegoPathActor::ParseAction(char* p_extra)
// FUNCTION: LEGO1 0x1002f1b0
// FUNCTION: BETA10 0x100af899
MxResult LegoPathActor::VTable0x9c()
MxResult LegoPathActor::CalculateSpline()
{
Mx3DPointFloat local34;
Mx3DPointFloat local48;
MxU32 local1c = 1;
MxU32 local20 = 1;
Mx3DPointFloat targetPosition;
Mx3DPointFloat endDirection;
MxU32 noPath1 = TRUE;
MxU32 noPath2 = TRUE;
if (m_grec != NULL) {
if (m_grec->GetBit1()) {
local1c = 0;
local20 = 0;
if (m_grec->HasPath()) {
noPath1 = FALSE;
noPath2 = FALSE;
Mx3DPointFloat vec;
switch (m_pathController->FUN_1004a240(*m_grec, local34, local48, m_unk0xe4, m_destEdge, m_boundary)) {
switch (m_pathController
->GetNextPathEdge(*m_grec, targetPosition, endDirection, m_destScale, m_destEdge, m_boundary)) {
case 0:
case 1:
break;
@ -651,30 +692,30 @@ MxResult LegoPathActor::VTable0x9c()
}
}
if (local1c != 0) {
SwitchBoundary(m_boundary, m_destEdge, m_unk0xe4);
if (noPath1 != FALSE) {
SwitchBoundary(m_boundary, m_destEdge, m_destScale);
}
if (local20 != 0) {
Mx3DPointFloat local78;
if (noPath2 != FALSE) {
Mx3DPointFloat normal;
assert(m_boundary && m_destEdge);
Vector3* v1 = m_destEdge->CWVertex(*m_boundary);
Vector3* v2 = m_destEdge->CCWVertex(*m_boundary);
Vector3* cw = m_destEdge->CWVertex(*m_boundary);
Vector3* ccw = m_destEdge->CCWVertex(*m_boundary);
assert(v1 && v2);
assert(cw && ccw);
LERP3(local34, *v1, *v2, m_unk0xe4);
LERP3(targetPosition, *cw, *ccw, m_destScale);
m_destEdge->GetFaceNormal(*m_boundary, local78);
local48.EqualsCross(*m_boundary->GetUp(), local78);
local48.Unitize();
m_destEdge->GetFaceNormal(*m_boundary, normal);
endDirection.EqualsCross(*m_boundary->GetUp(), normal);
endDirection.Unitize();
}
Vector3 rightRef(m_unk0xec[0]);
Vector3 upRef(m_unk0xec[1]);
Vector3 dirRef(m_unk0xec[2]);
Vector3 rightRef(m_local2World[0]);
Vector3 upRef(m_local2World[1]);
Vector3 dirRef(m_local2World[2]);
upRef = *m_boundary->GetUp();
@ -684,74 +725,74 @@ MxResult LegoPathActor::VTable0x9c()
dirRef.EqualsCross(rightRef, upRef);
dirRef.Unitize();
Mx3DPointFloat localc0(m_unk0xec[3]);
Mx3DPointFloat local84(m_unk0xec[2]);
Mx3DPointFloat local70(local34);
Mx3DPointFloat start(m_local2World[3]);
Mx3DPointFloat direction(m_local2World[2]);
Mx3DPointFloat startToTarget(targetPosition);
local70 -= localc0;
float len = local70.LenSquared();
startToTarget -= start;
float len = startToTarget.LenSquared();
if (len >= 0.0f) {
len = sqrt(len);
local84 *= len;
local48 *= len;
direction *= len;
endDirection *= len;
}
if (!m_userNavFlag) {
local84 *= -1.0f;
direction *= -1.0f;
}
if (VTable0x80(localc0, local84, local34, local48) != SUCCESS) {
if (SetSpline(start, direction, targetPosition, endDirection) != SUCCESS) {
MxTrace("Warning: m_BADuration = %g, roi = %s\n", m_BADuration, m_roi->GetName());
return FAILURE;
}
m_unk0x7c = 0.0f;
m_traveledDistance = 0.0f;
return SUCCESS;
}
// FUNCTION: LEGO1 0x1002f650
// FUNCTION: BETA10 0x100afd67
void LegoPathActor::VTable0xa4(MxBool& p_und1, MxS32& p_und2)
void LegoPathActor::GetWalkingBehavior(MxBool& p_countCounterclockWise, MxS32& p_selectedEdgeIndex)
{
switch (GetActorId()) {
case c_pepper:
p_und1 = TRUE;
p_und2 = 2;
p_countCounterclockWise = TRUE;
p_selectedEdgeIndex = 2;
break;
case c_mama:
p_und1 = FALSE;
p_und2 = 1;
p_countCounterclockWise = FALSE;
p_selectedEdgeIndex = 1;
break;
case c_papa:
p_und1 = TRUE;
p_und2 = 1;
p_countCounterclockWise = TRUE;
p_selectedEdgeIndex = 1;
break;
case c_nick:
case c_brickster:
p_und1 = TRUE;
p_und2 = SDL_rand(p_und2) + 1;
p_countCounterclockWise = TRUE;
p_selectedEdgeIndex = SDL_rand(p_selectedEdgeIndex) + 1;
break;
case c_laura:
p_und1 = FALSE;
p_und2 = 2;
p_countCounterclockWise = FALSE;
p_selectedEdgeIndex = 2;
break;
default:
p_und1 = TRUE;
p_und2 = 1;
p_countCounterclockWise = TRUE;
p_selectedEdgeIndex = 1;
break;
}
}
// FUNCTION: LEGO1 0x1002f700
// FUNCTION: BETA10 0x100afe4c
void LegoPathActor::VTable0xa8()
void LegoPathActor::ApplyLocal2World()
{
m_lastTime = Timer()->GetTime();
m_roi->SetLocal2World(m_unk0xec);
m_transformTime = Timer()->GetTime();
m_roi->SetLocal2World(m_local2World);
m_roi->WrappedUpdateWorldData();
if (m_userNavFlag) {
m_roi->WrappedSetLocal2WorldWithWorldDataUpdate(m_unk0xec);
m_roi->WrappedSetLocal2WorldWithWorldDataUpdate(m_local2World);
TransformPointOfView();
}
}

View File

@ -89,7 +89,7 @@ void LegoPathBoundary::SwitchBoundary(
LegoPathActor* p_actor,
LegoPathBoundary*& p_boundary,
LegoOrientedEdge*& p_edge,
float& p_unk0xe4
float& p_scale
)
{
LegoOrientedEdge* e = p_edge;
@ -101,7 +101,7 @@ void LegoPathBoundary::SwitchBoundary(
newBoundary = p_boundary;
}
MxS32 local10 = 0;
MxS32 availableEdgeCount = 0;
MxU8 userNavFlag;
if (e->BETA_1004a830(*newBoundary, 1)) {
@ -113,38 +113,38 @@ void LegoPathBoundary::SwitchBoundary(
do {
p_edge = (LegoOrientedEdge*) p_edge->GetCounterclockwiseEdge(*newBoundary);
LegoPathBoundary* local20 = (LegoPathBoundary*) p_edge->OtherFace(newBoundary);
LegoPathBoundary* otherBoundary = (LegoPathBoundary*) p_edge->OtherFace(newBoundary);
if (p_edge->GetMask0x03() && (userNavFlag || p_edge->BETA_1004a830(*local20, 1))) {
local10++;
if (p_edge->GetMask0x03() && (userNavFlag || p_edge->BETA_1004a830(*otherBoundary, 1))) {
availableEdgeCount++;
}
} while (p_edge != e);
MxBool localc = TRUE;
MxS32 local8 = local10 - 1;
MxBool countCounterclockwise = TRUE;
MxS32 selectedEdgeIndex = availableEdgeCount - 1;
if (local10 <= 1) {
local8 = 0;
if (availableEdgeCount <= 1) {
selectedEdgeIndex = 0;
}
else if (local10 == 2) {
local8 = 1;
else if (availableEdgeCount == 2) {
selectedEdgeIndex = 1;
}
else {
p_actor->VTable0xa4(localc, local8);
p_actor->GetWalkingBehavior(countCounterclockwise, selectedEdgeIndex);
}
while (local8 > 0) {
if (localc) {
while (selectedEdgeIndex > 0) {
if (countCounterclockwise) {
p_edge = (LegoOrientedEdge*) p_edge->GetCounterclockwiseEdge(*newBoundary);
}
else {
p_edge = (LegoOrientedEdge*) p_edge->GetClockwiseEdge(*newBoundary);
}
LegoPathBoundary* local20 = (LegoPathBoundary*) p_edge->OtherFace(newBoundary);
LegoPathBoundary* otherBoundary = (LegoPathBoundary*) p_edge->OtherFace(newBoundary);
if (p_edge->GetMask0x03() && (userNavFlag || p_edge->BETA_1004a830(*local20, 1))) {
local8--;
if (p_edge->GetMask0x03() && (userNavFlag || p_edge->BETA_1004a830(*otherBoundary, 1))) {
selectedEdgeIndex--;
}
}
@ -159,7 +159,7 @@ void LegoPathBoundary::SwitchBoundary(
p_boundary->AddActor(p_actor);
}
else {
p_unk0xe4 = 1.0 - p_unk0xe4;
p_scale = 1.0 - p_scale;
}
}
else {
@ -176,7 +176,7 @@ void LegoPathBoundary::SwitchBoundary(
p_edge = (LegoOrientedEdge*) p_edge->GetCounterclockwiseEdge(*p_boundary);
}
p_unk0xe4 = 1.0 - p_unk0xe4;
p_scale = 1.0 - p_scale;
}
}
@ -184,127 +184,128 @@ void LegoPathBoundary::SwitchBoundary(
// FUNCTION: BETA10 0x100b1adc
MxU32 LegoPathBoundary::Intersect(
float p_scale,
Vector3& p_point1,
Vector3& p_point2,
Vector3& p_point3,
Vector3& p_oldPos,
Vector3& p_newPos,
Vector3& p_intersectionPoint,
LegoOrientedEdge*& p_edge
)
{
LegoOrientedEdge* e = NULL;
float localc;
MxU32 local10 = 0;
float minHitDistance;
MxU32 normalizedCalculated = 0;
float len = 0.0f;
Mx3DPointFloat vec;
Mx3DPointFloat direction;
for (MxS32 i = 0; i < m_numEdges; i++) {
LegoOrientedEdge* edge = (LegoOrientedEdge*) m_edges[i];
if (p_point2.Dot(m_edgeNormals[i], p_point2) + m_edgeNormals[i][3] <= -1e-07) {
if (local10 == 0) {
local10 = 1;
vec = p_point2;
vec -= p_point1;
if (p_newPos.Dot(m_edgeNormals[i], p_newPos) + m_edgeNormals[i][3] <= -1e-07) {
if (normalizedCalculated == FALSE) {
normalizedCalculated = TRUE;
direction = p_newPos;
direction -= p_oldPos;
len = vec.LenSquared();
len = direction.LenSquared();
if (len <= 0.0f) {
return 0;
}
len = sqrt(len);
vec /= len;
direction /= len;
}
float dot = vec.Dot(vec, m_edgeNormals[i]);
float dot = direction.Dot(direction, m_edgeNormals[i]);
if (dot != 0.0f) {
float local34 = (-m_edgeNormals[i][3] - p_point1.Dot(p_point1, m_edgeNormals[i])) / dot;
float hitDistance = (-m_edgeNormals[i][3] - p_oldPos.Dot(p_oldPos, m_edgeNormals[i])) / dot;
if (local34 >= -0.001 && local34 <= len && (e == NULL || local34 < localc)) {
if (hitDistance >= -0.001 && hitDistance <= len && (e == NULL || hitDistance < minHitDistance)) {
e = edge;
localc = local34;
minHitDistance = hitDistance;
}
}
}
}
if (e != NULL) {
if (localc < 0.0f) {
localc = 0.0f;
if (minHitDistance < 0.0f) {
minHitDistance = 0.0f;
}
Mx3DPointFloat local50;
Mx3DPointFloat local70;
Vector3* local5c = e->CWVertex(*this);
Mx3DPointFloat startToPosition;
Mx3DPointFloat edgeNormal;
Vector3* start = e->CWVertex(*this);
p_point3 = vec;
p_point3 *= localc;
p_point3 += p_point1;
p_intersectionPoint = direction;
p_intersectionPoint *= minHitDistance;
p_intersectionPoint += p_oldPos;
local50 = p_point2;
local50 -= *local5c;
startToPosition = p_newPos;
startToPosition -= *start;
e->GetFaceNormal(*this, local70);
e->GetFaceNormal(*this, edgeNormal);
float local58 = local50.Dot(local50, local70);
LegoOrientedEdge* local54 = NULL;
float projection = startToPosition.Dot(startToPosition, edgeNormal);
LegoOrientedEdge* candidateEdge = NULL;
if (local58 < 0.0f) {
Mx3DPointFloat local84;
if (projection < 0.0f) {
Mx3DPointFloat candidateEdgeNormal;
for (LegoOrientedEdge* local88 = (LegoOrientedEdge*) e->GetClockwiseEdge(*this); e != local88;
local88 = (LegoOrientedEdge*) local88->GetClockwiseEdge(*this)) {
local88->GetFaceNormal(*this, local84);
for (LegoOrientedEdge* cwEdge = (LegoOrientedEdge*) e->GetClockwiseEdge(*this); e != cwEdge;
cwEdge = (LegoOrientedEdge*) cwEdge->GetClockwiseEdge(*this)) {
cwEdge->GetFaceNormal(*this, candidateEdgeNormal);
if (local84.Dot(local84, local70) <= 0.9) {
if (candidateEdgeNormal.Dot(candidateEdgeNormal, edgeNormal) <= 0.9) {
break;
}
Vector3* local90 = local88->CWVertex(*this);
Mx3DPointFloat locala4(p_point3);
locala4 -= *local90;
Vector3* candidateStart = cwEdge->CWVertex(*this);
Mx3DPointFloat candidateToIntersection(p_intersectionPoint);
candidateToIntersection -= *candidateStart;
float local8c = locala4.Dot(locala4, local84);
float candidateProjection = candidateToIntersection.Dot(candidateToIntersection, candidateEdgeNormal);
if (local8c > local58 && local8c < local88->m_length) {
local54 = local88;
local58 = local8c;
local70 = local84;
local5c = local90;
if (candidateProjection > projection && candidateProjection < cwEdge->m_length) {
candidateEdge = cwEdge;
projection = candidateProjection;
edgeNormal = candidateEdgeNormal;
start = candidateStart;
}
}
}
else {
if (e->m_length < local58) {
Mx3DPointFloat localbc;
if (e->m_length < projection) {
Mx3DPointFloat candidateEdgeNormal;
for (LegoOrientedEdge* locala8 = (LegoOrientedEdge*) e->GetCounterclockwiseEdge(*this); e != locala8;
locala8 = (LegoOrientedEdge*) locala8->GetCounterclockwiseEdge(*this)) {
locala8->GetFaceNormal(*this, localbc);
for (LegoOrientedEdge* ccwEdge = (LegoOrientedEdge*) e->GetCounterclockwiseEdge(*this); e != ccwEdge;
ccwEdge = (LegoOrientedEdge*) ccwEdge->GetCounterclockwiseEdge(*this)) {
ccwEdge->GetFaceNormal(*this, candidateEdgeNormal);
if (localbc.Dot(localbc, local70) <= 0.9) {
if (candidateEdgeNormal.Dot(candidateEdgeNormal, edgeNormal) <= 0.9) {
break;
}
Vector3* localc4 = locala8->CWVertex(*this);
Mx3DPointFloat locald8(p_point3);
locald8 -= *localc4;
Vector3* candidateStart = ccwEdge->CWVertex(*this);
Mx3DPointFloat candidateToIntersection(p_intersectionPoint);
candidateToIntersection -= *candidateStart;
float localc0 = locald8.Dot(locald8, localbc);
float candidateProjection =
candidateToIntersection.Dot(candidateToIntersection, candidateEdgeNormal);
if (localc0 < local58 && localc0 >= 0.0f) {
local54 = locala8;
local58 = localc0;
local70 = localbc;
local5c = localc4;
if (candidateProjection < projection && candidateProjection >= 0.0f) {
candidateEdge = ccwEdge;
projection = candidateProjection;
edgeNormal = candidateEdgeNormal;
start = candidateStart;
}
}
}
}
if (local54 != NULL) {
e = local54;
if (candidateEdge != NULL) {
e = candidateEdge;
}
if (local58 <= 0.0f) {
if (projection <= 0.0f) {
if (!e->GetMask0x03()) {
p_edge = (LegoOrientedEdge*) e->GetClockwiseEdge(*this);
}
@ -312,18 +313,18 @@ MxU32 LegoPathBoundary::Intersect(
p_edge = e;
}
p_point3 = *local5c;
p_intersectionPoint = *start;
return 2;
}
else if (local58 > 0.0f && e->m_length > local58) {
p_point3 = local70;
p_point3 *= local58;
p_point3 += *local5c;
else if (projection > 0.0f && e->m_length > projection) {
p_intersectionPoint = edgeNormal;
p_intersectionPoint *= projection;
p_intersectionPoint += *start;
p_edge = e;
return 1;
}
else {
p_point3 = *e->CCWVertex(*this);
p_intersectionPoint = *e->CCWVertex(*this);
if (!e->GetMask0x03()) {
p_edge = (LegoOrientedEdge*) e->GetCounterclockwiseEdge(*this);
@ -343,15 +344,15 @@ MxU32 LegoPathBoundary::Intersect(
// FUNCTION: BETA10 0x100b2220
MxU32 LegoPathBoundary::AddPresenterIfInRange(LegoAnimPresenter* p_presenter)
{
Mx3DPointFloat unk0x30;
Mx3DPointFloat centerDistance;
unk0x30 = m_centerPoint;
unk0x30 -= p_presenter->m_unk0xa8;
centerDistance = m_centerPoint;
centerDistance -= p_presenter->m_centerPoint;
float len = unk0x30.LenSquared();
float local20 = p_presenter->m_unk0xa4 + m_boundingRadius;
float len = centerDistance.LenSquared();
float radiusSquared = p_presenter->m_boundingRadius + m_boundingRadius;
if (len > 0.001 && len > local20 * local20) {
if (len > 0.001 && len > radiusSquared * radiusSquared) {
return 0;
}

View File

@ -14,10 +14,10 @@ DECOMP_SIZE_ASSERT(LegoPathController::CtrlBoundary, 0x08)
DECOMP_SIZE_ASSERT(LegoPathController::CtrlEdge, 0x08)
// GLOBAL: LEGO1 0x100d7cc8
MxU32 g_unk0x100d7cc8[] = {2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0};
MxU32 g_ctrlEdgesNamesA[] = {2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0};
// GLOBAL: LEGO1 0x100d7d08
MxU32 g_unk0x100d7d08[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
MxU32 g_ctrlEdgesNamesB[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// GLOBAL: LEGO1 0x100f42e8
// GLOBAL: BETA10 0x101f25f0
@ -28,7 +28,7 @@ LegoPathController::CtrlBoundary* LegoPathController::g_ctrlBoundariesA = NULL;
LegoPathController::CtrlEdge* LegoPathController::g_ctrlEdgesA = NULL;
// GLOBAL: LEGO1 0x100f42f0
const char* LegoPathController::g_unk0x100f42f0[] = {
const char* LegoPathController::g_ctrlBoundariesNamesA[] = {
"edg03_21",
"edg03_23",
"edg03_30",
@ -48,7 +48,7 @@ const char* LegoPathController::g_unk0x100f42f0[] = {
};
// GLOBAL: LEGO1 0x100f4330
const char* LegoPathController::g_unk0x100f4330[] = {
const char* LegoPathController::g_ctrlBoundariesNamesB[] = {
"edg03_06",
"edg03_21",
"edg03_30",
@ -108,23 +108,23 @@ MxResult LegoPathController::Create(
LegoPathBoundary& boundary = m_boundaries[i];
MxS32 j;
for (j = 0; j < sizeOfArray(g_unk0x100f42f0); j++) {
if (!SDL_strcasecmp(g_unk0x100f42f0[j], boundary.GetName())) {
for (j = 0; j < sizeOfArray(g_ctrlBoundariesNamesA); j++) {
if (!SDL_strcasecmp(g_ctrlBoundariesNamesA[j], boundary.GetName())) {
g_ctrlBoundariesA[j].m_controller = this;
g_ctrlBoundariesA[j].m_boundary = &boundary;
MxU32 edge = g_unk0x100d7cc8[j];
MxU32 edge = g_ctrlEdgesNamesA[j];
g_ctrlEdgesA[j].m_controller = this;
g_ctrlEdgesA[j].m_edge = boundary.GetEdges()[edge];
}
}
for (j = 0; j < sizeOfArray(g_unk0x100f4330); j++) {
if (!SDL_strcasecmp(g_unk0x100f4330[j], boundary.GetName())) {
for (j = 0; j < sizeOfArray(g_ctrlBoundariesNamesB); j++) {
if (!SDL_strcasecmp(g_ctrlBoundariesNamesB[j], boundary.GetName())) {
g_ctrlBoundariesB[j].m_controller = this;
g_ctrlBoundariesB[j].m_boundary = &boundary;
g_ctrlEdgesB[j].m_controller = this;
g_ctrlEdgesB[j].m_edge = boundary.GetEdges()[g_unk0x100d7d08[j]];
g_ctrlEdgesB[j].m_edge = boundary.GetEdges()[g_ctrlEdgesNamesB[j]];
}
}
}
@ -170,7 +170,7 @@ void LegoPathController::Destroy()
m_numE = 0;
MxS32 j;
for (j = 0; j < sizeOfArray(g_unk0x100f42f0); j++) {
for (j = 0; j < sizeOfArray(g_ctrlBoundariesNamesA); j++) {
if (g_ctrlBoundariesA[j].m_controller == this) {
g_ctrlBoundariesA[j].m_controller = NULL;
g_ctrlBoundariesA[j].m_boundary = NULL;
@ -182,7 +182,7 @@ void LegoPathController::Destroy()
}
}
for (j = 0; j < sizeOfArray(g_unk0x100f4330); j++) {
for (j = 0; j < sizeOfArray(g_ctrlBoundariesNamesB); j++) {
if (g_ctrlBoundariesB[j].m_controller == this) {
g_ctrlBoundariesB[j].m_controller = NULL;
g_ctrlBoundariesB[j].m_boundary = NULL;
@ -199,7 +199,7 @@ void LegoPathController::Destroy()
// FUNCTION: BETA10 0x100b6d60
MxResult LegoPathController::Tickle()
{
FUN_10046970();
AnimateActors();
return SUCCESS;
}
@ -230,8 +230,14 @@ MxResult LegoPathController::PlaceActor(
assert(pSrcE && pDestE);
float time = Timer()->GetTime();
MxResult result =
p_actor->VTable0x88(pBoundary, time, *pSrcE, p_srcScale, (LegoOrientedEdge&) *pDestE, p_destScale);
MxResult result = p_actor->SetTransformAndDestinationFromEdge(
pBoundary,
time,
*pSrcE,
p_srcScale,
(LegoOrientedEdge&) *pDestE,
p_destScale
);
if (result != SUCCESS) {
assert(0);
@ -305,7 +311,8 @@ MxResult LegoPathController::PlaceActor(
return FAILURE;
}
if (p_actor->VTable0x84(boundary, time, p_position, p_direction, edge, 0.5f) == SUCCESS) {
if (p_actor->SetTransformAndDestinationFromPoints(boundary, time, p_position, p_direction, edge, 0.5f) ==
SUCCESS) {
p_actor->SetController(this);
m_actors.insert(p_actor);
return SUCCESS;
@ -350,7 +357,7 @@ MxResult LegoPathController::RemoveActor(LegoPathActor* p_actor)
// FUNCTION: LEGO1 0x100468f0
// FUNCTION: BETA10 0x100b72f7
void LegoPathController::FUN_100468f0(LegoAnimPresenter* p_presenter)
void LegoPathController::AddPresenterIfInRange(LegoAnimPresenter* p_presenter)
{
for (MxS32 i = 0; i < m_numL; i++) {
if (!(m_boundaries[i].m_flags & LegoWEGEdge::c_bit3)) {
@ -370,7 +377,7 @@ void LegoPathController::RemovePresenterFromBoundaries(LegoAnimPresenter* p_pres
// FUNCTION: LEGO1 0x10046970
// FUNCTION: BETA10 0x100b73d8
void LegoPathController::FUN_10046970()
void LegoPathController::AnimateActors()
{
float time = Timer()->GetTime();
@ -388,7 +395,7 @@ void LegoPathController::FUN_10046970()
}
// FUNCTION: LEGO1 0x10046b30
MxResult LegoPathController::FUN_10046b30(LegoPathBoundary*& p_boundaries, MxS32& p_numL)
MxResult LegoPathController::GetBoundaries(LegoPathBoundary*& p_boundaries, MxS32& p_numL)
{
p_boundaries = m_boundaries;
p_numL = m_numL;
@ -410,7 +417,7 @@ LegoPathBoundary* LegoPathController::GetPathBoundary(const char* p_name)
// FUNCTION: LEGO1 0x10046bb0
// FUNCTION: BETA10 0x100b75bc
void LegoPathController::FUN_10046bb0(LegoWorld* p_world)
void LegoPathController::SetWorld(LegoWorld* p_world)
{
for (MxS32 i = 0; i < m_numT; i++) {
m_structs[i].SetWorld(p_world);
@ -437,10 +444,10 @@ MxResult LegoPathController::Init()
return FAILURE;
}
g_ctrlBoundariesA = new CtrlBoundary[sizeOfArray(g_unk0x100f42f0)];
g_ctrlEdgesA = new CtrlEdge[sizeOfArray(g_unk0x100f42f0)];
g_ctrlBoundariesB = new CtrlBoundary[sizeOfArray(g_unk0x100f4330)];
g_ctrlEdgesB = new CtrlEdge[sizeOfArray(g_unk0x100f4330)];
g_ctrlBoundariesA = new CtrlBoundary[sizeOfArray(g_ctrlBoundariesNamesA)];
g_ctrlEdgesA = new CtrlEdge[sizeOfArray(g_ctrlBoundariesNamesA)];
g_ctrlBoundariesB = new CtrlBoundary[sizeOfArray(g_ctrlBoundariesNamesB)];
g_ctrlEdgesB = new CtrlEdge[sizeOfArray(g_ctrlBoundariesNamesB)];
return SUCCESS;
}
@ -765,7 +772,7 @@ MxResult LegoPathController::ReadVector(LegoStorage* p_storage, Mx4DPointFloat&
// FUNCTION: LEGO1 0x10048310
// FUNCTION: BETA10 0x100b8911
MxResult LegoPathController::FUN_10048310(
MxResult LegoPathController::FindPath(
LegoPathEdgeContainer* p_grec,
const Vector3& p_oldPosition,
const Vector3& p_oldDirection,
@ -774,7 +781,7 @@ MxResult LegoPathController::FUN_10048310(
const Vector3& p_newDirection,
LegoPathBoundary* p_newBoundary,
LegoU8 p_mask,
MxFloat* p_param9
MxFloat* p_distance
)
{
p_grec->m_position = p_newPosition;
@ -782,22 +789,22 @@ MxResult LegoPathController::FUN_10048310(
p_grec->m_boundary = p_newBoundary;
if (p_newBoundary == p_oldBoundary) {
p_grec->SetBit1(TRUE);
p_grec->SetPath(TRUE);
return SUCCESS;
}
list<LegoBEWithFloat> boundaryList;
list<LegoBEWithFloat>::iterator boundaryListIt;
list<LegoBEWithMidpoint> boundaryList;
list<LegoBEWithMidpoint>::iterator boundaryListIt;
LegoBEWithFloatSet boundarySet;
LegoBEWithFloatSet::iterator boundarySetItA;
LegoBEWithFloatSet::iterator boundarySetItB;
LegoBEWithMidpointSet boundarySet;
LegoBEWithMidpointSet::iterator boundarySetItA;
LegoBEWithMidpointSet::iterator boundarySetItB;
LegoPathCtrlEdgeSet pathCtrlEdgeSet(m_pfsE);
MxFloat local14 = 999999.0f;
MxFloat minDistance = 999999.0f;
p_grec->SetBit1(FALSE);
p_grec->SetPath(FALSE);
for (MxS32 i = 0; i < p_oldBoundary->GetNumEdges(); i++) {
LegoPathCtrlEdge* edge = (LegoPathCtrlEdge*) p_oldBoundary->GetEdges()[i];
@ -809,15 +816,16 @@ MxResult LegoPathController::FUN_10048310(
if (p_newBoundary == otherFace) {
float dist;
if ((dist = edge->DistanceToMidpoint(p_oldPosition) + edge->DistanceToMidpoint(p_newPosition)) <
local14) {
local14 = dist;
minDistance) {
minDistance = dist;
p_grec->erase(p_grec->begin(), p_grec->end());
p_grec->SetBit1(TRUE);
p_grec->SetPath(TRUE);
p_grec->push_back(LegoBoundaryEdge(edge, p_oldBoundary));
}
}
else {
boundaryList.push_back(LegoBEWithFloat(edge, p_oldBoundary, edge->DistanceToMidpoint(p_oldPosition))
boundaryList.push_back(
LegoBEWithMidpoint(edge, p_oldBoundary, edge->DistanceToMidpoint(p_oldPosition))
);
boundarySet.insert(&boundaryList.back());
}
@ -827,10 +835,10 @@ MxResult LegoPathController::FUN_10048310(
pathCtrlEdgeSet.erase(edge);
}
if (!p_grec->GetBit1()) {
if (!p_grec->HasPath()) {
while (pathCtrlEdgeSet.size() > 0) {
LegoBEWithFloat edgeWithFloat;
MxFloat local70 = 999999.0f;
LegoBEWithMidpoint edgeWithMidpoint;
MxFloat minDist = 999999.0f;
boundarySetItA = boundarySetItB = boundarySet.begin();
@ -855,19 +863,20 @@ MxResult LegoPathController::FUN_10048310(
if (bOther == p_newBoundary) {
shouldRemove = FALSE;
LegoBEWithFloat* pfs = *boundarySetItA;
LegoBEWithMidpoint* pfs = *boundarySetItA;
assert(pfs);
float dist;
if ((dist = pfs->m_edge->DistanceToMidpoint(p_newPosition) + pfs->m_unk0x0c) < local70) {
edgeWithFloat.m_edge = NULL;
local70 = dist;
if ((dist = pfs->m_edge->DistanceToMidpoint(p_newPosition) + pfs->m_distanceToMidpoint) <
minDist) {
edgeWithMidpoint.m_edge = NULL;
minDist = dist;
// TODO: Match
if (dist < local14) {
local14 = dist;
if (dist < minDistance) {
minDistance = dist;
p_grec->erase(p_grec->begin(), p_grec->end());
p_grec->SetBit1(TRUE);
p_grec->SetPath(TRUE);
do {
p_grec->push_front(LegoBoundaryEdge(pfs->m_edge, pfs->m_boundary));
@ -885,10 +894,10 @@ MxResult LegoPathController::FUN_10048310(
shouldRemove = FALSE;
float dist;
if ((dist = edge->DistanceBetweenMidpoints(*e) + (*boundarySetItA)->m_unk0x0c) <
local70) {
local70 = dist;
edgeWithFloat = LegoBEWithFloat(edge, bOther, *boundarySetItA, dist);
if ((dist = edge->DistanceBetweenMidpoints(*e) +
(*boundarySetItA)->m_distanceToMidpoint) < minDist) {
minDist = dist;
edgeWithMidpoint = LegoBEWithMidpoint(edge, bOther, *boundarySetItA, dist);
}
}
}
@ -909,9 +918,9 @@ MxResult LegoPathController::FUN_10048310(
}
}
if (edgeWithFloat.m_edge != NULL) {
pathCtrlEdgeSet.erase(edgeWithFloat.m_edge);
boundaryList.push_back(edgeWithFloat);
if (edgeWithMidpoint.m_edge != NULL) {
pathCtrlEdgeSet.erase(edgeWithMidpoint.m_edge);
boundaryList.push_back(edgeWithMidpoint);
boundarySet.insert(&boundaryList.back());
}
else {
@ -920,7 +929,7 @@ MxResult LegoPathController::FUN_10048310(
}
}
if (p_grec->GetBit1()) {
if (p_grec->HasPath()) {
if (p_grec->size() > 0) {
LegoPathCtrlEdge* edge = p_grec->front().m_edge;
@ -941,8 +950,8 @@ MxResult LegoPathController::FUN_10048310(
}
}
if (p_param9 != NULL) {
*p_param9 = local14;
if (p_distance != NULL) {
*p_distance = minDistance;
}
return SUCCESS;
@ -953,20 +962,20 @@ MxResult LegoPathController::FUN_10048310(
// FUNCTION: LEGO1 0x1004a240
// FUNCTION: BETA10 0x100b9160
MxS32 LegoPathController::FUN_1004a240(
MxS32 LegoPathController::GetNextPathEdge(
LegoPathEdgeContainer& p_grec,
Vector3& p_v1,
Vector3& p_v2,
Vector3& p_position,
Vector3& p_direction,
float p_f1,
LegoOrientedEdge*& p_edge,
LegoPathBoundary*& p_boundary
)
{
if (p_grec.size() == 0) {
p_v1 = p_grec.m_position;
p_v2 = p_grec.m_direction;
p_position = p_grec.m_position;
p_direction = p_grec.m_direction;
p_boundary = p_grec.m_boundary;
p_grec.SetBit1(FALSE);
p_grec.SetPath(FALSE);
return 1;
}
@ -975,28 +984,28 @@ MxS32 LegoPathController::FUN_1004a240(
p_grec.pop_front();
Mx3DPointFloat vec;
p_v1 = *p_edge->CCWVertex(*p_boundary);
p_v1 -= *p_edge->CWVertex(*p_boundary);
p_v1 *= p_f1;
p_v1 += *p_edge->CWVertex(*p_boundary);
p_position = *p_edge->CCWVertex(*p_boundary);
p_position -= *p_edge->CWVertex(*p_boundary);
p_position *= p_f1;
p_position += *p_edge->CWVertex(*p_boundary);
p_edge->GetFaceNormal(*p_boundary, vec);
p_v2.EqualsCross(*p_boundary->GetUp(), vec);
p_direction.EqualsCross(*p_boundary->GetUp(), vec);
return 0;
}
// FUNCTION: LEGO1 0x1004a380
// FUNCTION: BETA10 0x100b957f
MxResult LegoPathController::FUN_1004a380(
Vector3& p_param1,
Vector3& p_param2,
Mx3DPointFloat* p_param3,
MxResult LegoPathController::FindIntersectionBoundary(
Vector3& p_location,
Vector3& p_direction,
Mx3DPointFloat* p_coefficients,
LegoPathBoundary*& p_boundary,
MxFloat& p_param5
MxFloat& p_apexParameter
)
{
MxFloat param5 = p_param5;
Mx3DPointFloat local24;
MxU32 local8 = TRUE;
MxFloat originalApexParameter = p_apexParameter;
Mx3DPointFloat intersectionPoint;
MxU32 solutionNotFound = TRUE;
for (MxS32 i = 0; i < m_numL; i++) {
if (m_boundaries[i].m_flags & LegoPathBoundary::c_bit3) {
@ -1004,75 +1013,76 @@ MxResult LegoPathController::FUN_1004a380(
}
LegoPathBoundary* b = &m_boundaries[i];
Mx4DPointFloat* unk0x14 = b->GetUp();
float local28 = p_param3[0].Dot(p_param3[0], *unk0x14);
Mx4DPointFloat* up = b->GetUp();
float coeffADotUp = p_coefficients[0].Dot(p_coefficients[0], *up);
if (local28 < 0.001 && local28 > -0.001) {
if (coeffADotUp < 0.001 && coeffADotUp > -0.001) {
continue;
}
float local2c = p_param3[1].Dot(p_param3[1], *unk0x14);
float local34 = p_param3[2].Dot(p_param3[2], *unk0x14) + unk0x14->index_operator(3);
float local3c = local2c * local2c - local34 * local28 * 4.0f;
float coeffBDotUp = p_coefficients[1].Dot(p_coefficients[1], *up);
float coeffCDotUp = p_coefficients[2].Dot(p_coefficients[2], *up) + up->index_operator(3);
float quadraticDiscriminant = coeffBDotUp * coeffBDotUp - coeffCDotUp * coeffADotUp * 4.0f;
if (local3c < -0.001) {
if (quadraticDiscriminant < -0.001) {
continue;
}
if (local3c < 0.0f) {
local3c = 0.0f;
if (quadraticDiscriminant < 0.0f) {
quadraticDiscriminant = 0.0f;
}
else {
local3c = sqrt(local3c);
quadraticDiscriminant = sqrt(quadraticDiscriminant);
}
float local38 = (local3c - local2c) / (local28 * 2.0f);
float local44 = (-local3c - local2c) / (local28 * 2.0f);
float intersectionParameter = (quadraticDiscriminant - coeffBDotUp) / (coeffADotUp * 2.0f);
float alternativeIntersectionParameter = (-quadraticDiscriminant - coeffBDotUp) / (coeffADotUp * 2.0f);
if (!IsBetween(local38, 0.0f, param5)) {
if (IsBetween(local44, 0.0f, param5)) {
local38 = local44;
if (!IsBetween(intersectionParameter, 0.0f, originalApexParameter)) {
if (IsBetween(alternativeIntersectionParameter, 0.0f, originalApexParameter)) {
intersectionParameter = alternativeIntersectionParameter;
}
else {
continue;
}
}
if (local8 || FUN_100c17a0(local38, p_param5, 0.0f, param5)) {
Mx3DPointFloat local58(p_param3[0]);
if (solutionNotFound ||
BothSameComparison(intersectionParameter, p_apexParameter, 0.0f, originalApexParameter)) {
Mx3DPointFloat tSqrA(p_coefficients[0]);
local58 *= local38 * local38;
local24 = p_param3[1];
local24 *= local38;
local24 += p_param3[2];
local24 += local58;
tSqrA *= intersectionParameter * intersectionParameter;
intersectionPoint = p_coefficients[1];
intersectionPoint *= intersectionParameter;
intersectionPoint += p_coefficients[2];
intersectionPoint += tSqrA;
assert(b->GetNumEdges() > 1);
MxS32 j;
for (j = b->GetNumEdges() - 1; j >= 0; j--) {
Mx4DPointFloat* local60 = b->GetEdgeNormal(j);
Mx4DPointFloat* edgeNormal = b->GetEdgeNormal(j);
if (local24.Dot(*local60, local24) + local60->index_operator(3) < -0.001) {
if (intersectionPoint.Dot(*edgeNormal, intersectionPoint) + edgeNormal->index_operator(3) < -0.001) {
break;
}
}
if (j < 0) {
Mx3DPointFloat local74(p_param1);
local74 -= local24;
Mx3DPointFloat direction(p_location);
direction -= intersectionPoint;
if (local74.Dot(local74, *unk0x14) >= 0.0f) {
p_param5 = local38;
if (direction.Dot(direction, *up) >= 0.0f) {
p_apexParameter = intersectionParameter;
p_boundary = b;
local8 = FALSE;
solutionNotFound = FALSE;
}
}
}
}
if (local8) {
p_param5 = param5;
if (solutionNotFound) {
p_apexParameter = originalApexParameter;
return FAILURE;
}

View File

@ -68,7 +68,7 @@ MxBool LegoPathStruct::HandleTrigger(LegoPathActor* p_actor, MxBool p_direction,
case c_h: {
LegoHideAnimPresenter* presenter = m_world->GetHideAnimPresenter();
if (presenter != NULL) {
presenter->FUN_1006db40(p_data * 100);
presenter->ApplyVisibility(p_data * 100);
}
break;
}

View File

@ -119,7 +119,7 @@ void CarRace::ReadyWorld()
{
assert(m_hideAnim);
LegoWorld::ReadyWorld();
m_hideAnim->FUN_1006db40(0);
m_hideAnim->ApplyVisibility(0);
MxDSAction action;
action.SetAtomId(*g_jukeboxScript);

View File

@ -83,7 +83,7 @@ void JetskiRace::ReadyWorld()
{
assert(m_hideAnim);
LegoWorld::ReadyWorld();
m_hideAnim->FUN_1006db40(0);
m_hideAnim->ApplyVisibility(0);
MxDSAction action;
action.SetAtomId(*g_jukeboxScript);
@ -216,7 +216,7 @@ MxLong JetskiRace::HandlePathStruct(LegoPathStructNotificationParam& p_param)
result = 1;
}
else if (m_playerLastPathStruct == 0xf) {
m_hideAnim->FUN_1006db40(m_playerLaps * 200 + 100);
m_hideAnim->ApplyVisibility(m_playerLaps * 200 + 100);
result = 1;
}

View File

@ -116,19 +116,19 @@ void LegoRace::Enable(MxBool p_enable)
// FUNCTION: LEGO1 0x10015f30
RaceState::RaceState()
{
m_entries[0].m_id = 1;
m_entries[0].m_id = LegoActor::c_pepper;
m_entries[0].m_lastScore = 0;
m_entries[0].m_score = 0;
m_entries[1].m_id = 2;
m_entries[1].m_id = LegoActor::c_mama;
m_entries[1].m_lastScore = 0;
m_entries[1].m_score = 0;
m_entries[2].m_id = 3;
m_entries[2].m_id = LegoActor::c_papa;
m_entries[2].m_lastScore = 0;
m_entries[2].m_score = 0;
m_entries[3].m_id = 4;
m_entries[3].m_id = LegoActor::c_nick;
m_entries[3].m_lastScore = 0;
m_entries[3].m_score = 0;
m_entries[4].m_id = 5;
m_entries[4].m_id = LegoActor::c_laura;
m_entries[4].m_lastScore = 0;
m_entries[4].m_score = 0;
m_state = RaceState::e_carrace;

View File

@ -25,9 +25,9 @@ LegoRaceActor::LegoRaceActor()
// FUNCTION: LEGO1 0x10014750
// FUNCTION: BETA10 0x100c9bba
MxS32 LegoRaceActor::VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3)
MxS32 LegoRaceActor::CheckIntersections(Vector3& p_rayOrigin, Vector3& p_rayEnd, Vector3& p_intersectionPoint)
{
MxS32 result = LegoPathActor::VTable0x68(p_v1, p_v2, p_v3);
MxS32 result = LegoPathActor::CheckIntersections(p_rayOrigin, p_rayEnd, p_intersectionPoint);
if (m_userNavFlag && result) {
MxLong time = Timer()->GetTime();
@ -46,20 +46,20 @@ MxS32 LegoRaceActor::VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3)
// FUNCTION: LEGO1 0x100147f0
// FUNCTION: BETA10 0x100c9c93
MxU32 LegoRaceActor::VTable0x90(float p_time, Matrix4& p_transform)
MxU32 LegoRaceActor::StepState(float p_time, Matrix4& p_transform)
{
// Note: Code duplication with LegoExtraActor::VTable0x90
// Note: Code duplication with LegoExtraActor::StepState
switch (m_actorState) {
case c_initial:
case c_one:
case c_ready:
return TRUE;
case c_two:
case c_hit:
m_unk0x08 = p_time + 2000.0f;
m_actorState = c_three;
m_actorTime += (p_time - m_lastTime) * m_worldSpeed;
m_lastTime = p_time;
m_actorState = c_hitAnimation;
m_actorTime += (p_time - m_transformTime) * m_worldSpeed;
m_transformTime = p_time;
return FALSE;
case c_three:
case c_hitAnimation:
assert(!m_userNavFlag);
Vector3 positionRef(p_transform[3]);
@ -73,10 +73,10 @@ MxU32 LegoRaceActor::VTable0x90(float p_time, Matrix4& p_transform)
p_transform.RotateX(0.6);
positionRef = position;
m_actorTime += (p_time - m_lastTime) * m_worldSpeed;
m_lastTime = p_time;
m_actorTime += (p_time - m_transformTime) * m_worldSpeed;
m_transformTime = p_time;
VTable0x74(p_transform);
ApplyTransform(p_transform);
return FALSE;
}
else {
@ -111,7 +111,7 @@ MxResult LegoRaceActor::HitActor(LegoPathActor* p_actor, MxBool p_bool)
roi->SetLocal2World(matr);
p_actor->SetActorState(c_two);
p_actor->SetActorState(c_hit);
}
}

View File

@ -15,7 +15,7 @@ DECOMP_SIZE_ASSERT(LegoRaceMap, 0x1b4)
// FUNCTION: BETA10 0x100ca2c0
LegoRaceMap::LegoRaceMap()
{
m_unk0x08 = FALSE;
m_mapEnabled = FALSE;
m_stillPresenter = NULL;
m_Map_Ctl = 0;
ControlManager()->Register(this);
@ -54,42 +54,42 @@ void LegoRaceMap::ParseAction(char* p_extra)
if (KeyValueStringParse(value, g_mapGeometry, p_extra)) {
char* token = strtok(value, g_parseExtraTokens);
if (token != NULL) {
m_unk0x14 = atof(token);
m_worldXOffset = atof(token);
}
token = strtok(NULL, g_parseExtraTokens);
if (token != NULL) {
m_unk0x18 = atof(token);
m_worldXScale = atof(token);
}
token = strtok(NULL, g_parseExtraTokens);
if (token != NULL) {
m_unk0x1c = atof(token);
m_worldZOffset = atof(token);
}
token = strtok(NULL, g_parseExtraTokens);
if (token != NULL) {
m_unk0x20 = atof(token);
m_worldZScale = atof(token);
}
token = strtok(NULL, g_parseExtraTokens);
if (token != NULL) {
m_unk0x24 = atof(token);
m_screenXScale = atof(token);
}
token = strtok(NULL, g_parseExtraTokens);
if (token != NULL) {
m_unk0x28 = atof(token);
m_screenYScale = atof(token);
}
token = strtok(NULL, g_parseExtraTokens);
if (token != NULL) {
m_unk0x2c = atof(token);
m_screenXOffset = atof(token);
}
token = strtok(NULL, g_parseExtraTokens);
if (token != NULL) {
m_unk0x30 = atof(token);
m_screenYOffset = atof(token);
}
}
@ -106,13 +106,13 @@ void LegoRaceMap::ParseAction(char* p_extra)
// FUNCTION: LEGO1 0x1005d4b0
// FUNCTION: BETA10 0x100ca849
void LegoRaceMap::FUN_1005d4b0()
void LegoRaceMap::UpdateMapLocatorPosition()
{
if (m_unk0x08) {
short xPos = (GetWorldPosition()[0] - m_unk0x14) / m_unk0x18 * m_unk0x24;
short yPos = (GetWorldPosition()[2] - m_unk0x1c) / m_unk0x20 * m_unk0x28;
if (m_mapEnabled) {
short xPos = (GetWorldPosition()[0] - m_worldXOffset) / m_worldXScale * m_screenXScale;
short yPos = (GetWorldPosition()[2] - m_worldZOffset) / m_worldZScale * m_screenYScale;
m_stillPresenter->SetPosition(xPos + m_unk0x2c, m_unk0x30 - yPos);
m_stillPresenter->SetPosition(xPos + m_screenXOffset, m_screenYOffset - yPos);
}
}
@ -130,12 +130,12 @@ MxLong LegoRaceMap::Notify(MxParam& p_param)
m_Map_Ctl->GetAction()->GetObjectId() == ((LegoControlManagerNotificationParam&) p_param).m_clickedObjectId) {
if (((LegoControlManagerNotificationParam&) p_param).m_enabledChild == 1) {
m_unk0x08 = TRUE;
FUN_1005d4b0();
m_mapEnabled = TRUE;
UpdateMapLocatorPosition();
m_stillPresenter->Enable(TRUE);
}
else {
m_unk0x08 = FALSE;
m_mapEnabled = FALSE;
m_stillPresenter->Enable(FALSE);
}
}

View File

@ -174,7 +174,7 @@ MxLong g_timeLastJetskiSoundPlayed = 0;
// FUNCTION: BETA10 0x100cad10
LegoRaceCar::LegoRaceCar()
{
m_userState = 0;
m_kickState = LEGORACECAR_NONE;
m_skelKick1Anim = 0;
m_skelKick2Anim = 0;
m_unk0x5c.Clear();
@ -304,11 +304,11 @@ void LegoRaceCar::KickCamera(float p_param)
LegoAnimActorStruct* a; // called `a` in BETA10
float deltaTime;
if (m_userState == LEGORACECAR_KICK1) {
if (m_kickState == LEGORACECAR_KICK1) {
a = m_skelKick1Anim;
}
else {
assert(m_userState == LEGORACECAR_KICK2);
assert(m_kickState == LEGORACECAR_KICK2);
a = m_skelKick2Anim;
}
@ -318,7 +318,7 @@ void LegoRaceCar::KickCamera(float p_param)
deltaTime = p_param - m_kickStart;
if (a->GetDuration() <= deltaTime || deltaTime < 0.0) {
if (m_userState == LEGORACECAR_KICK1) {
if (m_kickState == LEGORACECAR_KICK1) {
LegoOrientedEdge** edges = m_kick1B->GetEdges();
m_destEdge = edges[2];
m_boundary = m_kick1B;
@ -329,7 +329,7 @@ void LegoRaceCar::KickCamera(float p_param)
m_boundary = m_kick2B;
}
m_userState = LEGORACECAR_UNKNOWN_0;
m_kickState = LEGORACECAR_NONE;
}
else if (a->GetAnimTreePtr()->GetCamAnim()) {
MxMatrix transformationMatrix;
@ -373,12 +373,12 @@ MxU32 LegoRaceCar::HandleSkeletonKicks(float p_param1)
for (MxS32 i = 0; i < sizeOfArray(g_skeletonKickPhases); i++) {
if (m_boundary == current->m_edgeRef->m_b && current->m_lower <= skeletonCurAnimPhase &&
skeletonCurAnimPhase <= current->m_upper) {
m_userState = current->m_userState;
m_kickState = current->m_kickState;
}
current = &current[1];
}
if (m_userState != LEGORACECAR_KICK1 && m_userState != LEGORACECAR_KICK2) {
if (m_kickState != LEGORACECAR_KICK1 && m_kickState != LEGORACECAR_KICK2) {
MxTrace(
// STRING: BETA10 0x101f64c8
"Got kicked in boundary %s %d %g:%g %g\n",
@ -401,21 +401,21 @@ MxU32 LegoRaceCar::HandleSkeletonKicks(float p_param1)
// FUNCTION: BETA10 0x100cb88a
void LegoRaceCar::Animate(float p_time)
{
if (m_userNavFlag && (m_userState == LEGORACECAR_KICK1 || m_userState == LEGORACECAR_KICK2)) {
if (m_userNavFlag && (m_kickState == LEGORACECAR_KICK1 || m_kickState == LEGORACECAR_KICK2)) {
KickCamera(p_time);
return;
}
LegoCarRaceActor::Animate(p_time);
if (m_userNavFlag && m_userState == LEGORACECAR_UNKNOWN_1) {
if (m_userNavFlag && m_kickState == LEGORACECAR_NEAR_SKELETON) {
if (HandleSkeletonKicks(p_time)) {
return;
}
}
if (LegoCarRaceActor::m_animState == 1) {
FUN_1005d4b0();
UpdateMapLocatorPosition();
if (!m_userNavFlag) {
FUN_10080590(p_time);
@ -475,7 +475,7 @@ MxResult LegoRaceCar::HitActor(LegoPathActor* p_actor, MxBool p_bool)
Vector3(matr[3]) += g_hitOffset;
roi->SetLocal2World(matr);
p_actor->SetActorState(c_two);
p_actor->SetActorState(c_hit);
}
if (m_userNavFlag) {
@ -538,36 +538,36 @@ MxResult LegoRaceCar::HitActor(LegoPathActor* p_actor, MxBool p_bool)
// FUNCTION: LEGO1 0x10013600
// FUNCTION: BETA10 0x100cbe60
MxResult LegoRaceCar::VTable0x9c()
MxResult LegoRaceCar::CalculateSpline()
{
MxResult result;
if (m_userNavFlag) {
result = LegoCarRaceActor::VTable0x9c();
result = LegoCarRaceActor::CalculateSpline();
if (m_boundary) {
MxS32 bVar2 = 0;
MxS32 onSkeletonBoundary = FALSE;
for (MxS32 i = 0; i < sizeOfArray(g_skBMap); i++) {
assert(g_skBMap[i].m_b);
if (m_boundary == g_skBMap[i].m_b) {
bVar2 = 1;
onSkeletonBoundary = TRUE;
break;
}
}
if (m_userState == LEGORACECAR_UNKNOWN_1) {
if (!bVar2) {
m_userState = LEGORACECAR_UNKNOWN_0;
if (m_kickState == LEGORACECAR_NEAR_SKELETON) {
if (!onSkeletonBoundary) {
m_kickState = LEGORACECAR_NONE;
}
}
else {
m_userState = LEGORACECAR_UNKNOWN_1;
m_kickState = LEGORACECAR_NEAR_SKELETON;
}
}
}
else {
result = LegoCarRaceActor::VTable0x9c();
result = LegoCarRaceActor::CalculateSpline();
}
return result;
@ -598,7 +598,7 @@ void LegoJetski::SetWorldSpeed(MxFloat p_worldSpeed)
// FUNCTION: LEGO1 0x100136f0
// FUNCTION: BETA10 0x100cc01a
void LegoJetski::FUN_100136f0(float p_worldSpeed)
void LegoJetski::SetMaxLinearVelocity(float p_worldSpeed)
{
if (p_worldSpeed < 0) {
LegoCarRaceActor::m_animState = 2;
@ -617,7 +617,7 @@ void LegoJetski::Animate(float p_time)
LegoJetskiRaceActor::Animate(p_time);
if (LegoCarRaceActor::m_animState == 1) {
FUN_1005d4b0();
UpdateMapLocatorPosition();
if (!m_userNavFlag) {
FUN_10080590(p_time);
@ -692,7 +692,7 @@ MxResult LegoJetski::HitActor(LegoPathActor* p_actor, MxBool p_bool)
Vector3(matr[3]) += g_hitOffset;
roi->SetLocal2World(matr);
p_actor->SetActorState(c_two);
p_actor->SetActorState(c_hit);
}
if (m_userNavFlag) {

View File

@ -52,9 +52,9 @@ LegoCarRaceActor::LegoCarRaceActor()
m_unk0x10 = 0.65f;
m_unk0x14 = 0.03f;
m_unk0x18 = 0.6f;
m_unk0x140 = 0.1f;
m_unk0x150 = -5.0f;
m_unk0x148 = 1;
m_wallHitDirectionFactor = 0.1f;
m_linearRotationRatio = -5.0f;
m_canRotate = 1;
VariableTable()->SetVariable(g_fuel, "0.8");
}
@ -119,7 +119,7 @@ MxS32 LegoCarRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edg
Mx3DPointFloat destEdgeUnknownVector;
Mx3DPointFloat crossProduct;
if (m_actorState == c_one) {
if (m_actorState == c_ready) {
m_boundary = NULL;
// Not sure where the upper bound of 11 comes from, the underlying array has a size of 16
@ -133,7 +133,7 @@ MxS32 LegoCarRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edg
assert(m_boundary);
m_actorState = c_initial;
m_unk0x7c = 0;
m_traveledDistance = 0;
if (m_userNavFlag) {
NavController()->SetLinearVel(m_worldSpeed);
@ -146,7 +146,7 @@ MxS32 LegoCarRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edg
else {
for (MxS32 i = 0; i < 11; i += 2) {
if (LegoPathController::GetControlEdgeA(i) == p_edge) {
m_actorState = c_one;
m_actorState = c_ready;
if (m_worldSpeed < g_unk0x100f7aec) {
m_worldSpeed = g_unk0x100f7aec;
@ -158,9 +158,9 @@ MxS32 LegoCarRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edg
}
}
if (m_actorState == c_one) {
if (m_actorState == c_ready) {
if (m_userNavFlag) {
m_unk0xe4 = 0.5f;
m_destScale = 0.5f;
}
// variable names verified by BETA10
@ -168,7 +168,7 @@ MxS32 LegoCarRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edg
Vector3* v2 = m_destEdge->CWVertex(*m_boundary);
assert(v1 && v2);
LERP3(pointUnknown, *v1, *v2, m_unk0xe4);
LERP3(pointUnknown, *v1, *v2, m_destScale);
m_destEdge->GetFaceNormal(*m_boundary, destEdgeUnknownVector);
@ -185,14 +185,14 @@ MxS32 LegoCarRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edg
crossProduct *= 5.0f;
MxResult callResult =
VTable0x80(Vector3(m_roi->GetWorldPosition()), worldDirection, pointUnknown, crossProduct);
SetSpline(Vector3(m_roi->GetWorldPosition()), worldDirection, pointUnknown, crossProduct);
if (callResult) {
m_unk0x7c = 0;
m_traveledDistance = 0;
return 0;
}
else {
m_unk0x7c = 0;
m_traveledDistance = 0;
#ifdef BETA10
assert(0);
#endif
@ -217,7 +217,7 @@ MxS32 LegoCarRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edg
// FUNCTION: BETA10 0x100cdb3c
void LegoCarRaceActor::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoOrientedEdge*& p_edge, float& p_unk0xe4)
{
LegoPathActor::SwitchBoundary(m_boundary, m_destEdge, m_unk0xe4);
LegoPathActor::SwitchBoundary(m_boundary, m_destEdge, m_destScale);
}
// FUNCTION: LEGO1 0x10080b70
@ -230,7 +230,7 @@ void LegoCarRaceActor::Animate(float p_time)
if (SDL_strcasecmp(value, g_racing) == 0) {
m_animState = 1;
m_lastTime = p_time - 1.0f;
m_transformTime = p_time - 1.0f;
m_unk0x1c = p_time;
}
}
@ -242,14 +242,14 @@ void LegoCarRaceActor::Animate(float p_time)
// FUNCTION: LEGO1 0x10080be0
// FUNCTION: BETA10 0x100cdc54
MxResult LegoCarRaceActor::VTable0x9c()
MxResult LegoCarRaceActor::CalculateSpline()
{
LegoOrientedEdge* d = m_destEdge;
if (VTable0x1c(m_boundary, m_destEdge)) {
LegoPathBoundary* b = m_boundary;
SwitchBoundary(m_boundary, m_destEdge, m_unk0xe4);
SwitchBoundary(m_boundary, m_destEdge, m_destScale);
assert(m_boundary && m_destEdge);
// variable names verified by BETA10
@ -258,7 +258,7 @@ MxResult LegoCarRaceActor::VTable0x9c()
assert(v1 && v2);
Mx3DPointFloat point1;
LERP3(point1, *v1, *v2, m_unk0xe4);
LERP3(point1, *v1, *v2, m_destScale);
Mx3DPointFloat point2;
Mx3DPointFloat point3;
@ -277,7 +277,7 @@ MxResult LegoCarRaceActor::VTable0x9c()
point4 *= 5.0f;
point5 *= 5.0f;
MxResult res = VTable0x80(m_roi->GetWorldPosition(), point4, point1, point5);
MxResult res = SetSpline(m_roi->GetWorldPosition(), point4, point1, point5);
#ifdef BETA10
if (res) {
@ -286,7 +286,7 @@ MxResult LegoCarRaceActor::VTable0x9c()
}
#endif
m_unk0x7c = 0;
m_traveledDistance = 0;
}
return SUCCESS;
@ -299,7 +299,7 @@ LegoJetskiRaceActor::LegoJetskiRaceActor()
m_unk0x10 = 0.95f;
m_unk0x14 = 0.04f;
m_unk0x18 = 0.5f;
m_unk0x150 = 1.5f;
m_linearRotationRatio = 1.5f;
}
// FUNCTION: LEGO1 0x10081120
@ -315,7 +315,7 @@ MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_
Vector3* v1 = NULL;
Vector3* v2 = NULL;
if (m_actorState == c_one) {
if (m_actorState == c_ready) {
if (m_destEdge == LegoPathController::GetControlEdgeA(13)) {
m_boundary = (LegoPathBoundary*) m_destEdge->OtherFace(LegoPathController::GetControlBoundaryA(13));
}
@ -324,7 +324,7 @@ MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_
}
m_actorState = c_initial;
m_unk0x7c = 0;
m_traveledDistance = 0;
if (m_userNavFlag) {
NavController()->SetLinearVel(m_worldSpeed);
@ -336,7 +336,7 @@ MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_
}
else {
if (p_edge == LegoPathController::GetControlEdgeA(12)) {
m_actorState = c_one;
m_actorState = c_ready;
if (m_worldSpeed < g_unk0x100da044) {
m_worldSpeed = g_unk0x100da044;
@ -346,7 +346,7 @@ MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_
m_boundary = LegoPathController::GetControlBoundaryA(13);
}
else if (p_edge == LegoPathController::GetControlEdgeA(14)) {
m_actorState = c_one;
m_actorState = c_ready;
if (m_worldSpeed < g_unk0x100da044) {
m_worldSpeed = g_unk0x100da044;
@ -356,16 +356,16 @@ MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_
m_boundary = LegoPathController::GetControlBoundaryA(15);
}
if (m_actorState == c_one) {
if (m_actorState == c_ready) {
if (m_userNavFlag) {
m_unk0xe4 = 0.5f;
m_destScale = 0.5f;
}
v1 = m_destEdge->CCWVertex(*m_boundary);
v2 = m_destEdge->CWVertex(*m_boundary);
assert(v1 && v2);
LERP3(a, *v1, *v2, m_unk0xe4);
LERP3(a, *v1, *v2, m_destScale);
m_destEdge->GetFaceNormal(*m_boundary, bbb);
c.EqualsCross(bbb, *m_boundary->GetUp());
@ -377,9 +377,9 @@ MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_
worldDirection *= -1.0f;
}
if (VTable0x80(m_roi->GetWorldPosition(), worldDirection, a, c)) {
if (SetSpline(m_roi->GetWorldPosition(), worldDirection, a, c)) {
#ifndef BETA10
m_unk0x7c = 0;
m_traveledDistance = 0;
return 0;
#else
assert(0);
@ -387,7 +387,7 @@ MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_
#endif
}
m_unk0x7c = 0;
m_traveledDistance = 0;
return 0;
}
else {
@ -403,11 +403,11 @@ void LegoJetskiRaceActor::Animate(float p_time)
const LegoChar* raceState = VariableTable()->GetVariable(g_raceState);
if (!SDL_strcasecmp(raceState, g_racing)) {
m_animState = 1;
m_lastTime = p_time - 1.0f;
m_transformTime = p_time - 1.0f;
m_unk0x1c = p_time;
}
else if (!m_userNavFlag) {
LegoAnimActor::Animate(m_lastTime + 1.0f);
LegoAnimActor::Animate(m_transformTime + 1.0f);
}
}
@ -418,13 +418,13 @@ void LegoJetskiRaceActor::Animate(float p_time)
// FUNCTION: LEGO1 0x10081840
// FUNCTION: BETA10 0x100cf680
MxU32 LegoCarRaceActor::VTable0x6c(
MxU32 LegoCarRaceActor::CheckPresenterAndActorIntersections(
LegoPathBoundary* p_boundary,
Vector3& p_v1,
Vector3& p_v2,
float p_f1,
float p_f2,
Vector3& p_v3
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint
)
{
// STRING: LEGO1 0x100f7af4
@ -433,7 +433,7 @@ MxU32 LegoCarRaceActor::VTable0x6c(
LegoAnimPresenterSet& presenters = p_boundary->GetPresenters();
for (LegoAnimPresenterSet::iterator itap = presenters.begin(); itap != presenters.end(); itap++) {
if ((*itap)->VTable0x94(p_v1, p_v2, p_f1, p_f2, p_v3)) {
if ((*itap)->Intersect(p_rayOrigin, p_rayDirection, p_rayLength, p_radius, p_intersectionPoint)) {
return 1;
}
}
@ -457,8 +457,14 @@ MxU32 LegoCarRaceActor::VTable0x6c(
LegoROI* firstROI = (LegoROI*) co->front();
if (firstROI
->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) {
if (firstROI->Intersect(
p_rayOrigin,
p_rayDirection,
p_rayLength,
p_radius,
p_intersectionPoint,
m_collideBox && actor->GetCollideBox()
)) {
HitActor(actor, TRUE);
if (actor->HitActor(this, FALSE) < 0) {
@ -471,8 +477,14 @@ MxU32 LegoCarRaceActor::VTable0x6c(
LegoROI* lastROI = (LegoROI*) co->back();
if (lastROI
->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) {
if (lastROI->Intersect(
p_rayOrigin,
p_rayDirection,
p_rayLength,
p_radius,
p_intersectionPoint,
m_collideBox && actor->GetCollideBox()
)) {
HitActor(actor, TRUE);
if (actor->HitActor(this, FALSE) < 0) {
@ -485,7 +497,14 @@ MxU32 LegoCarRaceActor::VTable0x6c(
}
}
else {
if (roi->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) {
if (roi->Intersect(
p_rayOrigin,
p_rayDirection,
p_rayLength,
p_radius,
p_intersectionPoint,
m_collideBox && actor->GetCollideBox()
)) {
HitActor(actor, TRUE);
if (actor->HitActor(this, FALSE) < 0) {
@ -505,19 +524,19 @@ MxU32 LegoCarRaceActor::VTable0x6c(
}
// FUNCTION: LEGO1 0x10081fd0
MxU32 LegoJetskiRaceActor::VTable0x6c(
MxU32 LegoJetskiRaceActor::CheckPresenterAndActorIntersections(
LegoPathBoundary* p_boundary,
Vector3& p_v1,
Vector3& p_v2,
float p_f1,
float p_f2,
Vector3& p_v3
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint
)
{
LegoAnimPresenterSet& presenters = p_boundary->GetPresenters();
for (LegoAnimPresenterSet::iterator itap = presenters.begin(); itap != presenters.end(); itap++) {
if ((*itap)->VTable0x94(p_v1, p_v2, p_f1, p_f2, p_v3)) {
if ((*itap)->Intersect(p_rayOrigin, p_rayDirection, p_rayLength, p_radius, p_intersectionPoint)) {
return 1;
}
}
@ -533,7 +552,14 @@ MxU32 LegoJetskiRaceActor::VTable0x6c(
LegoROI* roi = actor->GetROI();
if (roi != NULL && (roi->GetVisibility() || actor->GetCameraFlag())) {
if (roi->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) {
if (roi->Intersect(
p_rayOrigin,
p_rayDirection,
p_rayLength,
p_radius,
p_intersectionPoint,
m_collideBox && actor->GetCollideBox()
)) {
HitActor(actor, TRUE);
if (actor->HitActor(this, FALSE) < 0) {

View File

@ -57,21 +57,21 @@ void LegoAnimPresenter::Init()
m_roiMapSize = 0;
m_managedActors = NULL;
m_sceneROIs = NULL;
m_unk0x78 = NULL;
m_transform = NULL;
m_flags = 0;
m_unk0xa8.Clear();
m_unk0xa4 = 0;
m_centerPoint.Clear();
m_boundingRadius = 0;
m_currentWorld = NULL;
m_unk0x95 = FALSE;
m_animationFinished = FALSE;
m_worldId = -1;
m_substMap = NULL;
m_worldAtom.Clear();
m_unk0x9c = 0;
m_unk0x8c = NULL;
m_unk0x90 = NULL;
m_unk0x94 = 0;
m_unk0x96 = TRUE;
m_unk0xa0 = NULL;
m_roiTransformApplied = 0;
m_ptAtCamROI = NULL;
m_ptAtCamNames = NULL;
m_ptAtCamCount = 0;
m_localActors = TRUE;
m_roiTransform = NULL;
}
// FUNCTION: LEGO1 0x10068770
@ -94,12 +94,12 @@ void LegoAnimPresenter::Destroy(MxBool p_fromDestructor)
}
if (m_managedActors != NULL) {
FUN_1006aa60();
ReleaseManagedActors();
delete m_managedActors;
}
if (m_unk0x78 != NULL) {
delete m_unk0x78;
if (m_transform != NULL) {
delete m_transform;
}
if (m_substMap != NULL) {
@ -115,22 +115,22 @@ void LegoAnimPresenter::Destroy(MxBool p_fromDestructor)
delete m_substMap;
}
if (m_unk0x90 != NULL) {
for (MxS32 i = 0; i < m_unk0x94; i++) {
if (m_unk0x90[i] != NULL) {
delete[] m_unk0x90[i];
if (m_ptAtCamNames != NULL) {
for (MxS32 i = 0; i < m_ptAtCamCount; i++) {
if (m_ptAtCamNames[i] != NULL) {
delete[] m_ptAtCamNames[i];
}
}
delete[] m_unk0x90;
delete[] m_ptAtCamNames;
}
if (m_unk0x8c != NULL) {
delete[] m_unk0x8c;
if (m_ptAtCamROI != NULL) {
delete[] m_ptAtCamROI;
}
if (m_unk0xa0 != NULL) {
delete m_unk0xa0;
if (m_roiTransform != NULL) {
delete m_roiTransform;
}
Init();
@ -153,16 +153,16 @@ MxResult LegoAnimPresenter::CreateAnim(MxStreamChunk* p_chunk)
if (storage.Read(&magicSig, sizeof(MxS32)) != SUCCESS || magicSig != 0x11) {
goto done;
}
if (storage.Read(&m_unk0xa4, sizeof(float)) != SUCCESS) {
if (storage.Read(&m_boundingRadius, sizeof(float)) != SUCCESS) {
goto done;
}
if (storage.Read(&m_unk0xa8[0], sizeof(float)) != SUCCESS) {
if (storage.Read(&m_centerPoint[0], sizeof(float)) != SUCCESS) {
goto done;
}
if (storage.Read(&m_unk0xa8[1], sizeof(float)) != SUCCESS) {
if (storage.Read(&m_centerPoint[1], sizeof(float)) != SUCCESS) {
goto done;
}
if (storage.Read(&m_unk0xa8[2], sizeof(float)) != SUCCESS) {
if (storage.Read(&m_centerPoint[2], sizeof(float)) != SUCCESS) {
goto done;
}
if (storage.Read(&parseScene, sizeof(LegoS32)) != SUCCESS) {
@ -193,24 +193,24 @@ MxResult LegoAnimPresenter::CreateAnim(MxStreamChunk* p_chunk)
}
// FUNCTION: LEGO1 0x10069150
LegoChar* LegoAnimPresenter::FUN_10069150(const LegoChar* p_und1)
LegoChar* LegoAnimPresenter::GetActorName(const LegoChar* p_name)
{
LegoChar* str;
if (LegoCharacterManager::IsActor(p_und1 + 1)) {
str = new LegoChar[strlen(p_und1)];
if (LegoCharacterManager::IsActor(p_name + 1)) {
str = new LegoChar[strlen(p_name)];
if (str != NULL) {
strcpy(str, p_und1 + 1);
strcpy(str, p_name + 1);
}
}
else {
LegoChar buffer[32];
sprintf(buffer, "%d", m_action->GetUnknown24());
str = new LegoChar[strlen(p_und1) + strlen(buffer) + strlen(GetActionObjectName()) + 1];
str = new LegoChar[strlen(p_name) + strlen(buffer) + strlen(GetActionObjectName()) + 1];
if (str != NULL) {
strcpy(str, p_und1);
strcpy(str, p_name);
strcat(str, buffer);
strcat(str, GetActionObjectName());
}
@ -220,7 +220,7 @@ LegoChar* LegoAnimPresenter::FUN_10069150(const LegoChar* p_und1)
}
// FUNCTION: LEGO1 0x100692b0
void LegoAnimPresenter::FUN_100692b0()
void LegoAnimPresenter::CreateManagedActors()
{
m_managedActors = new LegoROIList();
@ -232,7 +232,7 @@ void LegoAnimPresenter::FUN_100692b0()
LegoU32 actorType = m_anim->GetActorType(i);
LegoROI* roi = NULL;
if (actorType == LegoAnimActorEntry::e_actorType2) {
if (actorType == LegoAnimActorEntry::e_managedLegoActor) {
LegoChar* src;
if (str[0] == '*') {
src = str + 1;
@ -247,44 +247,44 @@ void LegoAnimPresenter::FUN_100692b0()
roi->SetVisibility(FALSE);
}
}
else if (actorType == LegoAnimActorEntry::e_actorType4) {
else if (actorType == LegoAnimActorEntry::e_managedInvisibleRoi) {
LegoChar* baseName = new LegoChar[strlen(str)];
strcpy(baseName, str + 1);
SDL_strlwr(baseName);
LegoChar* und = FUN_10069150(str);
roi = CharacterManager()->FUN_10085a80(und, baseName, TRUE);
LegoChar* roiName = GetActorName(str);
roi = CharacterManager()->FUN_10085a80(roiName, baseName, TRUE);
if (roi != NULL) {
roi->SetVisibility(FALSE);
}
delete[] baseName;
delete[] und;
delete[] roiName;
}
else if (actorType == LegoAnimActorEntry::e_actorType3) {
else if (actorType == LegoAnimActorEntry::e_managedInvisibleRoiTrimmed) {
LegoChar* lodName = new LegoChar[strlen(str)];
strcpy(lodName, str + 1);
for (LegoChar* i = &lodName[strlen(lodName) - 1]; i > lodName; i--) {
if ((*i < '0' || *i > '9') && *i != '_') {
for (LegoChar* c = &lodName[strlen(lodName) - 1]; c > lodName; c--) {
if ((*c < '0' || *c > '9') && *c != '_') {
break;
}
*i = '\0';
*c = '\0';
}
SDL_strlwr(lodName);
LegoChar* und = FUN_10069150(str);
roi = CharacterManager()->CreateAutoROI(und, lodName, TRUE);
LegoChar* roiName = GetActorName(str);
roi = CharacterManager()->CreateAutoROI(roiName, lodName, TRUE);
if (roi != NULL) {
roi->SetVisibility(FALSE);
}
delete[] lodName;
delete[] und;
delete[] roiName;
}
if (roi != NULL) {
@ -298,7 +298,7 @@ void LegoAnimPresenter::FUN_100692b0()
// FUNCTION: LEGO1 0x100695c0
// FUNCTION: BETA10 0x1004f359
void LegoAnimPresenter::FUN_100695c0()
void LegoAnimPresenter::CreateSceneROIs()
{
m_sceneROIs = new LegoROIList();
@ -307,10 +307,10 @@ void LegoAnimPresenter::FUN_100695c0()
LegoU32 numActors = m_anim->GetNumActors();
for (LegoU32 i = 0; i < numActors; i++) {
if (FUN_100698b0(rois, m_anim->GetActorName(i)) == FALSE) {
if (AppendROIToScene(rois, m_anim->GetActorName(i)) == FALSE) {
LegoU32 actorType = m_anim->GetActorType(i);
if (actorType == LegoAnimActorEntry::e_actorType5 || actorType == LegoAnimActorEntry::e_actorType6) {
if (actorType == LegoAnimActorEntry::e_sceneRoi1 || actorType == LegoAnimActorEntry::e_sceneRoi2) {
LegoChar lodName[256];
const LegoChar* actorName = m_anim->GetActorName(i);
@ -324,7 +324,7 @@ void LegoAnimPresenter::FUN_100695c0()
SDL_strlwr(lodName);
CharacterManager()->CreateAutoROI(actorName, lodName, FALSE);
FUN_100698b0(rois, actorName);
AppendROIToScene(rois, actorName);
}
}
}
@ -359,13 +359,13 @@ LegoChar* LegoAnimPresenter::GetVariableOrIdentity(const LegoChar* p_varName, co
}
// FUNCTION: LEGO1 0x100698b0
LegoBool LegoAnimPresenter::FUN_100698b0(const CompoundObject& p_rois, const LegoChar* p_und2)
LegoBool LegoAnimPresenter::AppendROIToScene(const CompoundObject& p_rois, const LegoChar* p_varName)
{
LegoBool result = FALSE;
LegoChar* str;
if (*(str = GetVariableOrIdentity(p_und2, NULL)) == '*') {
LegoChar* tmp = FUN_10069150(str);
if (*(str = GetVariableOrIdentity(p_varName, NULL)) == '*') {
LegoChar* tmp = GetActorName(str);
delete[] str;
str = tmp;
}
@ -410,12 +410,12 @@ LegoROI* LegoAnimPresenter::FindROI(const LegoChar* p_name)
}
// FUNCTION: LEGO1 0x10069b10
void LegoAnimPresenter::FUN_10069b10()
void LegoAnimPresenter::BuildROIMap()
{
LegoAnimStructMap anims;
if (m_unk0x8c != NULL) {
memset(m_unk0x8c, 0, m_unk0x94 * sizeof(*m_unk0x8c));
if (m_ptAtCamROI != NULL) {
memset(m_ptAtCamROI, 0, m_ptAtCamCount * sizeof(*m_ptAtCamROI));
}
UpdateStructMapAndROIIndex(anims, m_anim->GetRoot(), NULL);
@ -434,10 +434,10 @@ void LegoAnimPresenter::FUN_10069b10()
m_roiMap[index] = (*it).second.m_roi;
if (m_roiMap[index]->GetName() != NULL) {
for (MxS32 i = 0; i < m_unk0x94; i++) {
if (m_unk0x8c[i] == NULL && m_unk0x90[i] != NULL) {
if (!SDL_strcasecmp(m_unk0x90[i], m_roiMap[index]->GetName())) {
m_unk0x8c[i] = m_roiMap[index];
for (MxS32 i = 0; i < m_ptAtCamCount; i++) {
if (m_ptAtCamROI[i] == NULL && m_ptAtCamNames[i] != NULL) {
if (!SDL_strcasecmp(m_ptAtCamNames[i], m_roiMap[index]->GetName())) {
m_ptAtCamROI[i] = m_roiMap[index];
break;
}
}
@ -461,7 +461,7 @@ void LegoAnimPresenter::UpdateStructMapAndROIIndex(LegoAnimStructMap& p_map, Leg
if (name != NULL && *name != '-') {
if (*name == '*') {
name = und2 = FUN_10069150(name);
name = und2 = GetActorName(name);
}
und = GetVariableOrIdentity(name, p_roi != NULL ? p_roi->GetName() : NULL);
@ -506,13 +506,13 @@ void LegoAnimPresenter::UpdateStructMapAndROIIndex(LegoAnimStructMap& p_map, Leg
void LegoAnimPresenter::UpdateStructMapAndROIIndexForNode(
LegoAnimStructMap& p_map,
LegoAnimNodeData* p_data,
const LegoChar* p_und,
const LegoChar* p_key,
LegoROI* p_roi
)
{
LegoAnimStructMap::iterator it;
it = p_map.find(p_und);
it = p_map.find(p_key);
if (it == p_map.end()) {
LegoAnimStruct animStruct;
animStruct.m_index = p_map.size() + 1;
@ -520,10 +520,10 @@ void LegoAnimPresenter::UpdateStructMapAndROIIndexForNode(
p_data->SetROIIndex(animStruct.m_index);
LegoChar* und = new LegoChar[strlen(p_und) + 1];
strcpy(und, p_und);
LegoChar* key = new LegoChar[strlen(p_key) + 1];
strcpy(key, p_key);
p_map[und] = animStruct;
p_map[key] = animStruct;
}
else {
p_data->SetROIIndex((*it).second.m_index);
@ -532,7 +532,7 @@ void LegoAnimPresenter::UpdateStructMapAndROIIndexForNode(
// FUNCTION: LEGO1 0x1006aa60
// FUNCTION: BETA10 0x1004feee
void LegoAnimPresenter::FUN_1006aa60()
void LegoAnimPresenter::ReleaseManagedActors()
{
LegoROIListCursor cursor(m_managedActors);
LegoROI* roi;
@ -540,16 +540,16 @@ void LegoAnimPresenter::FUN_1006aa60()
while (cursor.Next(roi)) {
const char* name = roi->GetName();
if (m_unk0x96 || !CharacterManager()->IsActor(name)) {
if (m_localActors || !CharacterManager()->IsActor(name)) {
CharacterManager()->ReleaseActor(name);
}
}
}
// FUNCTION: LEGO1 0x1006ab70
void LegoAnimPresenter::FUN_1006ab70()
void LegoAnimPresenter::AppendManagedActors()
{
if (m_unk0x96) {
if (m_localActors) {
AnimationManager()->FUN_10063270(m_managedActors, this);
}
else {
@ -558,25 +558,25 @@ void LegoAnimPresenter::FUN_1006ab70()
}
// FUNCTION: LEGO1 0x1006aba0
LegoBool LegoAnimPresenter::FUN_1006aba0()
LegoBool LegoAnimPresenter::VerifyAnimationTree()
{
return FUN_1006abb0(m_anim->GetRoot(), 0);
return VerifyAnimationNode(m_anim->GetRoot(), NULL);
}
// FUNCTION: LEGO1 0x1006abb0
MxBool LegoAnimPresenter::FUN_1006abb0(LegoTreeNode* p_node, LegoROI* p_roi)
MxBool LegoAnimPresenter::VerifyAnimationNode(LegoTreeNode* p_node, LegoROI* p_roi)
{
MxBool result = FALSE;
LegoROI* roi = p_roi;
LegoChar* und = NULL;
LegoChar* varOrName = NULL;
const LegoChar* name = ((LegoAnimNodeData*) p_node->GetData())->GetName();
MxS32 i, count;
if (name != NULL && *name != '-') {
und = GetVariableOrIdentity(name, p_roi != NULL ? p_roi->GetName() : NULL);
varOrName = GetVariableOrIdentity(name, p_roi != NULL ? p_roi->GetName() : NULL);
if (p_roi == NULL) {
roi = FindROI(und);
roi = FindROI(varOrName);
if (roi == NULL) {
goto done;
@ -587,7 +587,7 @@ MxBool LegoAnimPresenter::FUN_1006abb0(LegoTreeNode* p_node, LegoROI* p_roi)
if (child == NULL) {
if (FindROI(name) != NULL) {
if (FUN_1006abb0(p_node, NULL)) {
if (VerifyAnimationNode(p_node, NULL)) {
result = TRUE;
}
}
@ -599,7 +599,7 @@ MxBool LegoAnimPresenter::FUN_1006abb0(LegoTreeNode* p_node, LegoROI* p_roi)
count = p_node->GetNumChildren();
for (i = 0; i < count; i++) {
if (!FUN_1006abb0(p_node->GetChild(i), roi)) {
if (!VerifyAnimationNode(p_node->GetChild(i), roi)) {
goto done;
}
}
@ -607,8 +607,8 @@ MxBool LegoAnimPresenter::FUN_1006abb0(LegoTreeNode* p_node, LegoROI* p_roi)
result = TRUE;
done:
if (und != NULL) {
delete[] und;
if (varOrName != NULL) {
delete[] varOrName;
}
return result;
@ -640,12 +640,12 @@ void LegoAnimPresenter::PutFrame()
time = 0;
}
FUN_1006b9a0(m_anim, time, m_unk0x78);
ApplyTransformWithVisibilityAndCam(m_anim, time, m_transform);
if (m_unk0x8c != NULL && m_currentWorld != NULL && m_currentWorld->GetCameraController() != NULL) {
for (MxS32 i = 0; i < m_unk0x94; i++) {
if (m_unk0x8c[i] != NULL) {
MxMatrix mat(m_unk0x8c[i]->GetLocal2World());
if (m_ptAtCamROI != NULL && m_currentWorld != NULL && m_currentWorld->GetCameraController() != NULL) {
for (MxS32 i = 0; i < m_ptAtCamCount; i++) {
if (m_ptAtCamROI[i] != NULL) {
MxMatrix mat(m_ptAtCamROI[i]->GetLocal2World());
Vector3 pos(mat[0]);
Vector3 dir(mat[1]);
@ -667,8 +667,8 @@ void LegoAnimPresenter::PutFrame()
dir *= dirsqr;
up *= upsqr;
m_unk0x8c[i]->SetLocal2World(mat);
m_unk0x8c[i]->WrappedUpdateWorldData();
m_ptAtCamROI[i]->SetLocal2World(mat);
m_ptAtCamROI[i]->WrappedUpdateWorldData();
}
}
}
@ -677,7 +677,7 @@ void LegoAnimPresenter::PutFrame()
// FUNCTION: LEGO1 0x1006afc0
// FUNCTION: BETA10 0x1005059a
MxResult LegoAnimPresenter::FUN_1006afc0(MxMatrix*& p_matrix, float p_und)
MxResult LegoAnimPresenter::GetTransforms(MxMatrix*& p_matrix, float p_time)
{
MxU32 length = m_roiMapSize + 1;
p_matrix = new MxMatrix[length];
@ -689,7 +689,7 @@ MxResult LegoAnimPresenter::FUN_1006afc0(MxMatrix*& p_matrix, float p_und)
}
}
FUN_1006b900(m_anim, p_und, m_unk0x78);
ApplyTransform(m_anim, p_time, m_transform);
for (i = 1; i < length; i++) {
MxMatrix mat;
@ -706,7 +706,7 @@ MxResult LegoAnimPresenter::FUN_1006afc0(MxMatrix*& p_matrix, float p_und)
// FUNCTION: LEGO1 0x1006b140
// FUNCTION: BETA10 0x100507e0
MxResult LegoAnimPresenter::FUN_1006b140(LegoROI* p_roi)
MxResult LegoAnimPresenter::CopyTransform(LegoROI* p_roi)
{
if (p_roi == NULL) {
return FAILURE;
@ -720,16 +720,16 @@ MxResult LegoAnimPresenter::FUN_1006b140(LegoROI* p_roi)
MxMatrix inverse;
const Matrix4& local2world = p_roi->GetLocal2World();
MxMatrix* local5c;
MxMatrix* roiTransforms;
MxU32 i;
if (FUN_1006afc0(local5c, 0.0f) != SUCCESS) {
if (GetTransforms(roiTransforms, 0.0f) != SUCCESS) {
goto done;
}
for (i = 1; i <= m_roiMapSize; i++) {
if (m_roiMap[i] == p_roi) {
if (local5c[i].Invert(inverse) != SUCCESS) {
if (roiTransforms[i].Invert(inverse) != SUCCESS) {
goto done;
}
@ -739,15 +739,15 @@ MxResult LegoAnimPresenter::FUN_1006b140(LegoROI* p_roi)
{
mn->Product(inverse, local2world);
SetUnknown0xa0(mn);
delete[] local5c;
SetUnknown0x0cTo1();
SetRoiTransform(mn);
delete[] roiTransforms;
SetRoiTransformApplied();
MxMatrix local140(*m_unk0x78);
MxMatrix localf8;
MxMatrix originalTransform(*m_transform);
MxMatrix newTransform;
localf8.Product(local140, *m_unk0xa0);
*m_unk0x78 = localf8;
newTransform.Product(originalTransform, *m_roiTransform);
*m_transform = newTransform;
return SUCCESS;
}
@ -756,8 +756,8 @@ MxResult LegoAnimPresenter::FUN_1006b140(LegoROI* p_roi)
delete mn;
}
if (local5c != NULL) {
delete[] local5c;
if (roiTransforms != NULL) {
delete[] roiTransforms;
}
return FAILURE;
@ -793,22 +793,22 @@ void LegoAnimPresenter::ReadyTickle()
void LegoAnimPresenter::StartingTickle()
{
SubstituteVariables();
FUN_100692b0();
FUN_100695c0();
CreateManagedActors();
CreateSceneROIs();
if (m_flags & c_mustSucceed && !FUN_1006aba0()) {
if (m_flags & c_mustSucceed && !VerifyAnimationTree()) {
goto done;
}
FUN_10069b10();
BuildROIMap();
SetDisabled(TRUE);
if (m_unk0x78 == NULL) {
if (m_transform == NULL) {
if (fabs(m_action->GetDirection()[0]) >= 0.00000047683716F ||
fabs(m_action->GetDirection()[1]) >= 0.00000047683716F ||
fabs(m_action->GetDirection()[2]) >= 0.00000047683716F) {
m_unk0x78 = new MxMatrix();
CalcLocalTransform(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp(), *m_unk0x78);
m_transform = new MxMatrix();
CalcLocalTransform(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp(), *m_transform);
}
else if (m_roiMap != NULL) {
LegoROI* roi = m_roiMap[1];
@ -816,14 +816,14 @@ void LegoAnimPresenter::StartingTickle()
if (roi != NULL) {
MxMatrix mat;
mat = roi->GetLocal2World();
m_unk0x78 = new MxMatrix(mat);
m_transform = new MxMatrix(mat);
}
}
}
if ((m_action->GetDuration() == -1 || ((MxDSMediaAction*) m_action)->GetSustainTime() == -1) &&
m_compositePresenter) {
m_compositePresenter->VTable0x60(this);
m_compositePresenter->AdvanceSerialAction(this);
}
else {
m_action->SetTimeStarted(Timer()->GetTime());
@ -832,11 +832,11 @@ void LegoAnimPresenter::StartingTickle()
ProgressTickleState(e_streaming);
if (m_compositePresenter && m_compositePresenter->IsA("LegoAnimMMPresenter")) {
m_unk0x96 = ((LegoAnimMMPresenter*) m_compositePresenter)->FUN_1004b8b0();
m_compositePresenter->VTable0x60(this);
m_localActors = ((LegoAnimMMPresenter*) m_compositePresenter)->FUN_1004b8b0();
m_compositePresenter->AdvanceSerialAction(this);
}
VTable0x8c();
AddToWorld();
done:
if (m_sceneROIs != NULL) {
@ -853,17 +853,17 @@ void LegoAnimPresenter::StreamingTickle()
m_subscriber->FreeDataChunk(chunk);
}
if (m_unk0x95) {
if (m_animationFinished) {
ProgressTickleState(e_done);
if (m_compositePresenter) {
if (m_compositePresenter->IsA("LegoAnimMMPresenter")) {
m_compositePresenter->VTable0x60(this);
m_compositePresenter->AdvanceSerialAction(this);
}
}
}
else {
if (m_action->GetElapsedTime() > m_anim->GetDuration() + m_action->GetStartTime()) {
m_unk0x95 = TRUE;
m_animationFinished = TRUE;
}
}
}
@ -894,7 +894,7 @@ const char* LegoAnimPresenter::GetActionObjectName()
// FUNCTION: LEGO1 0x1006b900
// FUNCTION: BETA10 0x100510d8
void LegoAnimPresenter::FUN_1006b900(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix)
void LegoAnimPresenter::ApplyTransform(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix)
{
LegoTreeNode* root = p_anim->GetRoot();
MxMatrix mat;
@ -919,7 +919,7 @@ void LegoAnimPresenter::FUN_1006b900(LegoAnim* p_anim, MxLong p_time, Matrix4* p
// FUNCTION: LEGO1 0x1006b9a0
// FUNCTION: BETA10 0x1005118b
void LegoAnimPresenter::FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix)
void LegoAnimPresenter::ApplyTransformWithVisibilityAndCam(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix)
{
LegoTreeNode* root = p_anim->GetRoot();
MxMatrix mat;
@ -1010,43 +1010,43 @@ void LegoAnimPresenter::ParseExtra()
}
if (KeyValueStringParse(output, g_strPTATCAM, extraCopy)) {
list<char*> tmp;
list<char*> tokens;
if (m_unk0x90 != NULL) {
for (MxS32 i = 0; i < m_unk0x94; i++) {
if (m_unk0x90[i] != NULL) {
if (m_ptAtCamNames != NULL) {
for (MxS32 i = 0; i < m_ptAtCamCount; i++) {
if (m_ptAtCamNames[i] != NULL) {
// (modernization) critical bug: wrong free
delete[] m_unk0x90;
delete[] m_ptAtCamNames;
}
}
delete[] m_unk0x90;
m_unk0x90 = NULL;
delete[] m_ptAtCamNames;
m_ptAtCamNames = NULL;
}
if (m_unk0x8c != NULL) {
delete[] m_unk0x8c;
m_unk0x8c = NULL;
if (m_ptAtCamROI != NULL) {
delete[] m_ptAtCamROI;
m_ptAtCamROI = NULL;
}
char* token = strtok(output, g_parseExtraTokens);
while (token != NULL) {
char* valueCopy = new char[strlen(token) + 1];
strcpy(valueCopy, token);
tmp.push_back(valueCopy);
tokens.push_back(valueCopy);
token = strtok(NULL, g_parseExtraTokens);
}
m_unk0x94 = tmp.size();
if (m_unk0x94 != 0) {
m_unk0x8c = new LegoROI*[m_unk0x94];
m_unk0x90 = new char*[m_unk0x94];
memset(m_unk0x8c, 0, sizeof(*m_unk0x8c) * m_unk0x94);
memset(m_unk0x90, 0, sizeof(*m_unk0x90) * m_unk0x94);
m_ptAtCamCount = tokens.size();
if (m_ptAtCamCount != 0) {
m_ptAtCamROI = new LegoROI*[m_ptAtCamCount];
m_ptAtCamNames = new char*[m_ptAtCamCount];
memset(m_ptAtCamROI, 0, sizeof(*m_ptAtCamROI) * m_ptAtCamCount);
memset(m_ptAtCamNames, 0, sizeof(*m_ptAtCamNames) * m_ptAtCamCount);
MxS32 i = 0;
for (list<char*>::iterator it = tmp.begin(); it != tmp.end(); it++, i++) {
m_unk0x90[i] = *it;
for (list<char*>::iterator it = tokens.begin(); it != tokens.end(); it++, i++) {
m_ptAtCamNames[i] = *it;
}
}
}
@ -1055,13 +1055,13 @@ void LegoAnimPresenter::ParseExtra()
// FUNCTION: LEGO1 0x1006c570
// FUNCTION: BETA10 0x10051ab3
void LegoAnimPresenter::VTable0xa0(Matrix4& p_matrix)
void LegoAnimPresenter::SetTransform(Matrix4& p_matrix)
{
if (m_unk0x78 != NULL) {
delete m_unk0x78;
if (m_transform != NULL) {
delete m_transform;
}
m_unk0x78 = new MxMatrix(p_matrix);
m_transform = new MxMatrix(p_matrix);
}
// FUNCTION: LEGO1 0x1006c620
@ -1090,7 +1090,7 @@ void LegoAnimPresenter::EndAction()
}
if (m_anim != NULL) {
FUN_1006b9a0(m_anim, m_anim->GetDuration(), m_unk0x78);
ApplyTransformWithVisibilityAndCam(m_anim, m_anim->GetDuration(), m_transform);
}
if (m_roiMapSize != 0 && m_roiMap != NULL && m_roiMap[1] != NULL && m_flags & c_hideOnStop) {
@ -1102,8 +1102,8 @@ void LegoAnimPresenter::EndAction()
}
SetDisabled(FALSE);
FUN_1006ab70();
VTable0x90();
AppendManagedActors();
RemoveFromWorld();
if (m_currentWorld != NULL) {
m_currentWorld->Remove(this);
@ -1114,24 +1114,24 @@ void LegoAnimPresenter::EndAction()
// FUNCTION: LEGO1 0x1006c7a0
// FUNCTION: BETA10 0x10051da6
void LegoAnimPresenter::FUN_1006c7a0()
void LegoAnimPresenter::ApplyFinishedTransform()
{
if (m_anim != NULL) {
FUN_1006b9a0(m_anim, m_anim->GetDuration(), m_unk0x78);
ApplyTransformWithVisibilityAndCam(m_anim, m_anim->GetDuration(), m_transform);
}
m_unk0x95 = TRUE;
m_animationFinished = TRUE;
}
// FUNCTION: LEGO1 0x1006c7d0
// FUNCTION: BETA10 0x10051e07
void LegoAnimPresenter::VTable0x8c()
void LegoAnimPresenter::AddToWorld()
{
if (m_unk0x78) {
m_unk0xa8 += (*m_unk0x78)[3];
if (m_transform) {
m_centerPoint += (*m_transform)[3];
}
else {
m_unk0xa8 += m_action->GetLocation();
m_centerPoint += m_action->GetLocation();
}
if (m_currentWorld == NULL) {
@ -1148,7 +1148,7 @@ void LegoAnimPresenter::VTable0x8c()
// FUNCTION: LEGO1 0x1006c860
// FUNCTION: BETA10 0x10051f45
void LegoAnimPresenter::VTable0x90()
void LegoAnimPresenter::RemoveFromWorld()
{
if (m_currentWorld != NULL) {
m_currentWorld->RemovePresenterFromBoundaries(this);
@ -1182,26 +1182,34 @@ void LegoAnimPresenter::SetDisabled(MxBool p_disabled)
// FUNCTION: LEGO1 0x1006c8f0
// FUNCTION: BETA10 0x1005206c
MxU32 LegoAnimPresenter::VTable0x94(Vector3& p_v1, Vector3& p_v2, float p_f1, float p_f2, Vector3& p_v3)
MxU32 LegoAnimPresenter::Intersect(
Vector3& p_rayOrigin,
Vector3& p_rayDirection,
float p_rayLength,
float p_radius,
Vector3& p_intersectionPoint
)
{
Mx3DPointFloat a, b;
Mx3DPointFloat centerToRay, rayEnd;
b = p_v2;
b *= p_f1;
b += p_v1;
rayEnd = p_rayDirection;
rayEnd *= p_rayLength;
rayEnd += p_rayOrigin;
a = b;
a -= m_unk0xa8;
centerToRay = rayEnd;
centerToRay -= m_centerPoint;
float len = a.LenSquared();
float len = centerToRay.LenSquared();
if (len <= 0.0f) {
return TRUE;
}
len = sqrt(len);
if (len <= m_unk0xa4 + p_f2 && m_roiMapSize != 0 && m_roiMap != NULL) {
if (len <= m_boundingRadius + p_radius && m_roiMapSize != 0 && m_roiMap != NULL) {
for (MxU32 i = 1; i <= m_roiMapSize; i++) {
if (m_roiMap[i]->GetLODCount() != 0 && m_roiMap[i]->Intersect(p_v1, p_v2, p_f1, p_f2, p_v3, FALSE)) {
if (m_roiMap[i]->GetLODCount() != 0 &&
m_roiMap[i]
->Intersect(p_rayOrigin, p_rayDirection, p_rayLength, p_radius, p_intersectionPoint, FALSE)) {
return TRUE;
}
}
@ -1212,7 +1220,7 @@ MxU32 LegoAnimPresenter::VTable0x94(Vector3& p_v1, Vector3& p_v2, float p_f1, fl
// FUNCTION: LEGO1 0x1006ca50
// FUNCTION: BETA10 0x100521d0
MxResult LegoAnimPresenter::VTable0x98(LegoPathBoundary* p_boundary)
MxResult LegoAnimPresenter::AddActors(LegoPathBoundary* p_boundary)
{
for (MxU32 i = 1; i <= m_roiMapSize; i++) {
LegoEntity* entity = m_roiMap[i]->GetEntity();
@ -1234,18 +1242,18 @@ void LegoLoopingAnimPresenter::StreamingTickle()
m_subscriber->FreeDataChunk(chunk);
}
if (m_unk0x95) {
if (m_animationFinished) {
ProgressTickleState(e_done);
if (m_compositePresenter) {
if (m_compositePresenter->IsA("LegoAnimMMPresenter")) {
m_compositePresenter->VTable0x60(this);
m_compositePresenter->AdvanceSerialAction(this);
}
}
}
else {
if (m_action->GetDuration() != -1) {
if (m_action->GetElapsedTime() > m_action->GetDuration() + m_action->GetStartTime()) {
m_unk0x95 = TRUE;
m_animationFinished = TRUE;
}
}
}
@ -1264,12 +1272,12 @@ void LegoLoopingAnimPresenter::PutFrame()
time = 0;
}
FUN_1006b9a0(m_anim, time, m_unk0x78);
ApplyTransformWithVisibilityAndCam(m_anim, time, m_transform);
if (m_unk0x8c != NULL && m_currentWorld != NULL && m_currentWorld->GetCameraController() != NULL) {
for (MxS32 i = 0; i < m_unk0x94; i++) {
if (m_unk0x8c[i] != NULL) {
MxMatrix mat(m_unk0x8c[i]->GetLocal2World());
if (m_ptAtCamROI != NULL && m_currentWorld != NULL && m_currentWorld->GetCameraController() != NULL) {
for (MxS32 i = 0; i < m_ptAtCamCount; i++) {
if (m_ptAtCamROI[i] != NULL) {
MxMatrix mat(m_ptAtCamROI[i]->GetLocal2World());
Vector3 pos(mat[0]);
Vector3 dir(mat[1]);
@ -1291,8 +1299,8 @@ void LegoLoopingAnimPresenter::PutFrame()
dir *= dirsqr;
up *= upsqr;
m_unk0x8c[i]->SetLocal2World(mat);
m_unk0x8c[i]->WrappedUpdateWorldData();
m_ptAtCamROI[i]->SetLocal2World(mat);
m_ptAtCamROI[i]->WrappedUpdateWorldData();
}
}
}
@ -1318,7 +1326,7 @@ void LegoLocomotionAnimPresenter::Init()
m_unk0xcc = -1;
m_unk0xd0 = -1;
m_roiMapList = NULL;
m_unk0xd4 = 0;
m_worldRefCounter = 0;
}
// FUNCTION: LEGO1 0x1006d0e0
@ -1387,7 +1395,7 @@ void LegoLocomotionAnimPresenter::ReadyTickle()
SendToCompositePresenter(Lego());
}
m_unk0xd4++;
m_worldRefCounter++;
}
}
@ -1408,7 +1416,7 @@ void LegoLocomotionAnimPresenter::StartingTickle()
// FUNCTION: LEGO1 0x1006d660
void LegoLocomotionAnimPresenter::StreamingTickle()
{
if (m_unk0xd4 == 0) {
if (m_worldRefCounter == 0) {
EndAction();
}
}
@ -1423,7 +1431,7 @@ void LegoLocomotionAnimPresenter::EndAction()
// FUNCTION: LEGO1 0x1006d680
// FUNCTION: BETA10 0x10052b3d
void LegoLocomotionAnimPresenter::FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value)
void LegoLocomotionAnimPresenter::CreateROIAndBuildMap(LegoAnimActor* p_actor, MxFloat p_worldSpeed)
{
// This asserts that LegoLocomotionAnimPresenter is contained in legoanimpresenter.cpp
AUTOLOCK(m_criticalSection);
@ -1433,12 +1441,12 @@ void LegoLocomotionAnimPresenter::FUN_1006d680(LegoAnimActor* p_actor, MxFloat p
const char* key = ((LegoAnimNodeData*) m_anim->GetRoot()->GetData())->GetName();
variableTable->SetVariable(key, p_actor->GetROI()->GetName());
FUN_100695c0();
FUN_10069b10();
CreateSceneROIs();
BuildROIMap();
if (m_roiMap != NULL) {
m_roiMapList->Append(m_roiMap);
p_actor->CreateAnimActorStruct(m_anim, p_value, m_roiMap, m_roiMapSize);
p_actor->CreateAnimActorStruct(m_anim, p_worldSpeed, m_roiMap, m_roiMapSize);
m_roiMap = NULL;
}
@ -1529,21 +1537,21 @@ void LegoHideAnimPresenter::StartingTickle()
LegoLoopingAnimPresenter::StartingTickle();
if (m_currentTickleState == e_streaming) {
FUN_1006dc10();
FUN_1006db40(0);
AssignIndiciesWithMap();
ApplyVisibility(0);
}
}
// FUNCTION: LEGO1 0x1006db40
// FUNCTION: BETA10 0x100531ab
void LegoHideAnimPresenter::FUN_1006db40(LegoTime p_time)
void LegoHideAnimPresenter::ApplyVisibility(LegoTime p_time)
{
FUN_1006db60(m_anim->GetRoot(), p_time);
ApplyVisibility(m_anim->GetRoot(), p_time);
}
// FUNCTION: LEGO1 0x1006db60
// FUNCTION: BETA10 0x100531de
void LegoHideAnimPresenter::FUN_1006db60(LegoTreeNode* p_node, LegoTime p_time)
void LegoHideAnimPresenter::ApplyVisibility(LegoTreeNode* p_node, LegoTime p_time)
{
LegoAnimNodeData* data = (LegoAnimNodeData*) p_node->GetData();
MxBool newB = FALSE;
@ -1564,23 +1572,23 @@ void LegoHideAnimPresenter::FUN_1006db60(LegoTreeNode* p_node, LegoTime p_time)
if (boundary != NULL) {
newB = data->GetVisibility(p_time);
previousB = boundary->GetFlag0x10();
boundary->SetFlag0x10(newB);
previousB = boundary->GetVisibility();
boundary->SetVisibility(newB);
}
}
for (MxS32 i = 0; i < p_node->GetNumChildren(); i++) {
FUN_1006db60(p_node->GetChild(i), p_time);
ApplyVisibility(p_node->GetChild(i), p_time);
}
}
// FUNCTION: LEGO1 0x1006dc10
// FUNCTION: BETA10 0x100532fd
void LegoHideAnimPresenter::FUN_1006dc10()
void LegoHideAnimPresenter::AssignIndiciesWithMap()
{
LegoHideAnimStructMap anims;
FUN_1006e3f0(anims, m_anim->GetRoot());
BuildMap(anims, m_anim->GetRoot());
if (m_boundaryMap != NULL) {
delete[] m_boundaryMap;
@ -1597,7 +1605,7 @@ void LegoHideAnimPresenter::FUN_1006dc10()
// FUNCTION: LEGO1 0x1006e3f0
// FUNCTION: BETA10 0x1005345e
void LegoHideAnimPresenter::FUN_1006e3f0(LegoHideAnimStructMap& p_map, LegoTreeNode* p_node)
void LegoHideAnimPresenter::BuildMap(LegoHideAnimStructMap& p_map, LegoTreeNode* p_node)
{
LegoAnimNodeData* data = (LegoAnimNodeData*) p_node->GetData();
const char* name = data->GetName();
@ -1606,7 +1614,7 @@ void LegoHideAnimPresenter::FUN_1006e3f0(LegoHideAnimStructMap& p_map, LegoTreeN
LegoPathBoundary* boundary = m_currentWorld->FindPathBoundary(name);
if (boundary != NULL) {
FUN_1006e470(p_map, data, name, boundary);
CheckedAdd(p_map, data, name, boundary);
}
else {
data->SetBoundaryIndex(0);
@ -1615,13 +1623,13 @@ void LegoHideAnimPresenter::FUN_1006e3f0(LegoHideAnimStructMap& p_map, LegoTreeN
MxS32 count = p_node->GetNumChildren();
for (MxS32 i = 0; i < count; i++) {
FUN_1006e3f0(p_map, p_node->GetChild(i));
BuildMap(p_map, p_node->GetChild(i));
}
}
// FUNCTION: LEGO1 0x1006e470
// FUNCTION: BETA10 0x10053520
void LegoHideAnimPresenter::FUN_1006e470(
void LegoHideAnimPresenter::CheckedAdd(
LegoHideAnimStructMap& p_map,
LegoAnimNodeData* p_data,
const char* p_name,

View File

@ -141,7 +141,7 @@ MxResult LegoTexturePresenter::PutData()
// FUNCTION: LEGO1 0x1004fcb0
void LegoTexturePresenter::DoneTickle()
{
if (this->m_compositePresenter && !this->m_compositePresenter->VTable0x64(2)) {
if (this->m_compositePresenter && !this->m_compositePresenter->GetActionEnded(2)) {
SetTickleState(e_idle);
return;
}

View File

@ -331,15 +331,15 @@ MxResult Act3::ShootPizza(LegoPathController* p_controller, Vector3& p_location,
m_pizzas[nextPizza].Create(this, TRUE, nextPizza);
if (m_pizzas[nextPizza].FUN_10053b40(p_location, p_direction, p_up) != SUCCESS) {
if (m_pizzas[nextPizza].CalculateArc(p_location, p_direction, p_up) != SUCCESS) {
return FAILURE;
}
MxFloat unk0x19c = *m_pizzas[nextPizza].GetUnknown0x19c();
if (p_controller->FUN_1004a380(
MxFloat unk0x19c = *m_pizzas[nextPizza].GetApexParameter();
if (p_controller->FindIntersectionBoundary(
p_location,
p_direction,
m_pizzas[nextPizza].GetUnknown0x160(),
m_pizzas[nextPizza].GetCoefficients(),
boundary,
unk0x19c
) == SUCCESS) {
@ -354,7 +354,7 @@ MxResult Act3::ShootPizza(LegoPathController* p_controller, Vector3& p_location,
direction -= m_brickster->GetROI()->GetLocal2World()[3];
local18 = FALSE;
if (m_pizzas[nextPizza].FUN_10053cb0(p_controller, boundary, unk0x19c) == SUCCESS) {
if (m_pizzas[nextPizza].Shoot(p_controller, boundary, unk0x19c) == SUCCESS) {
p_controller->PlaceActor(&m_pizzas[nextPizza]);
boundary->AddActor(&m_pizzas[nextPizza]);
m_pizzas[nextPizza].SetWorldSpeed(10.0f);
@ -362,7 +362,7 @@ MxResult Act3::ShootPizza(LegoPathController* p_controller, Vector3& p_location,
}
}
if (local18 && m_pizzas[nextPizza].FUN_10053d30(p_controller, unk0x19c) == SUCCESS) {
if (local18 && m_pizzas[nextPizza].Shoot(p_controller, unk0x19c) == SUCCESS) {
p_controller->PlaceActor(&m_pizzas[nextPizza]);
m_pizzas[nextPizza].SetWorldSpeed(10.0f);
return SUCCESS;
@ -386,26 +386,26 @@ MxResult Act3::ShootDonut(LegoPathController* p_controller, Vector3& p_location,
m_donuts[nextDonut].Create(this, FALSE, nextDonut);
if (m_donuts[nextDonut].FUN_10053b40(p_location, p_direction, p_up) != SUCCESS) {
if (m_donuts[nextDonut].CalculateArc(p_location, p_direction, p_up) != SUCCESS) {
return FAILURE;
}
MxFloat unk0x19c = *m_donuts[nextDonut].GetUnknown0x19c();
if (p_controller->FUN_1004a380(
MxFloat unk0x19c = *m_donuts[nextDonut].GetApexParameter();
if (p_controller->FindIntersectionBoundary(
p_location,
p_direction,
m_donuts[nextDonut].GetUnknown0x160(),
m_donuts[nextDonut].GetCoefficients(),
boundary,
unk0x19c
) == SUCCESS) {
if (m_donuts[nextDonut].FUN_10053cb0(p_controller, boundary, unk0x19c) == SUCCESS) {
if (m_donuts[nextDonut].Shoot(p_controller, boundary, unk0x19c) == SUCCESS) {
p_controller->PlaceActor(&m_donuts[nextDonut]);
boundary->AddActor(&m_donuts[nextDonut]);
m_donuts[nextDonut].SetWorldSpeed(10.0f);
return SUCCESS;
}
}
else if (m_donuts[nextDonut].FUN_10053d30(p_controller, unk0x19c) == SUCCESS) {
else if (m_donuts[nextDonut].Shoot(p_controller, unk0x19c) == SUCCESS) {
p_controller->PlaceActor(&m_donuts[nextDonut]);
m_donuts[nextDonut].SetWorldSpeed(10.0f);
return SUCCESS;
@ -583,13 +583,13 @@ MxLong Act3::Notify(MxParam& p_param)
m_cop1->SetActorState(LegoPathActor::c_initial);
m_cop1->SetWorldSpeed(2.0f);
m_cop1->VTable0xa8();
m_cop1->ApplyLocal2World();
m_cop2->SetActorState(LegoPathActor::c_initial);
m_cop2->SetWorldSpeed(2.0f);
m_cop2->VTable0xa8();
m_cop2->ApplyLocal2World();
m_brickster->VTable0xa8();
m_brickster->ApplyLocal2World();
m_pizzaHitSound = 0;
m_pizzaMissSound = 0;
m_copDonutSound = 0;
@ -912,44 +912,44 @@ void Act3::Enable(MxBool p_enable)
MxFloat delta = Timer()->GetTime() - m_time - 100.0f;
m_time = -1.0f;
m_cop1->SetLastTime(m_cop1->GetLastTime() + delta);
m_cop1->SetTransformTime(m_cop1->GetTransformTime() + delta);
m_cop1->SetActorTime(m_cop1->GetActorTime() + delta);
m_cop1->SetUnknown0x20(m_cop1->GetUnknown0x20() + delta);
m_cop1->SetUnknown0x1c(m_cop1->GetUnknown0x1c() + delta);
m_cop2->SetLastTime(m_cop2->GetLastTime() + delta);
m_cop2->SetTransformTime(m_cop2->GetTransformTime() + delta);
m_cop2->SetActorTime(m_cop2->GetActorTime() + delta);
m_cop2->SetUnknown0x20(m_cop2->GetUnknown0x20() + delta);
m_cop2->SetUnknown0x1c(m_cop2->GetUnknown0x1c() + delta);
m_brickster->SetLastTime(m_brickster->GetLastTime() + delta);
m_brickster->SetTransformTime(m_brickster->GetTransformTime() + delta);
m_brickster->SetActorTime(m_brickster->GetActorTime() + delta);
m_brickster->SetUnknown0x20(m_brickster->GetUnknown0x20() + delta);
m_brickster->SetUnknown0x24(m_brickster->GetUnknown0x24() + delta);
m_brickster->SetUnknown0x50(m_brickster->GetUnknown0x50() + delta);
m_brickster->SetUnknown0x1c(m_brickster->GetUnknown0x1c() + delta);
m_copter->SetLastTime(m_copter->GetLastTime() + delta);
m_copter->SetTransformTime(m_copter->GetTransformTime() + delta);
m_copter->SetActorTime(m_copter->GetActorTime() + delta);
m_shark->SetLastTime(m_shark->GetLastTime() + delta);
m_shark->SetTransformTime(m_shark->GetTransformTime() + delta);
m_shark->SetActorTime(m_shark->GetActorTime() + delta);
m_shark->SetUnknown0x2c(m_shark->GetUnknown0x2c() + delta);
MxS32 i;
for (i = 0; i < (MxS32) sizeOfArray(m_pizzas); i++) {
if (m_pizzas[i].IsValid()) {
m_pizzas[i].SetLastTime(m_pizzas[i].GetLastTime() + delta);
m_pizzas[i].SetTransformTime(m_pizzas[i].GetTransformTime() + delta);
m_pizzas[i].SetActorTime(m_pizzas[i].GetActorTime() + delta);
m_pizzas[i].SetUnknown0x158(m_pizzas[i].GetUnknown0x158() + delta);
m_pizzas[i].SetRotateTimeout(m_pizzas[i].GetRotateTimeout() + delta);
}
}
for (i = 0; i < (MxS32) sizeOfArray(m_donuts); i++) {
if (m_donuts[i].IsValid()) {
m_donuts[i].SetLastTime(m_donuts[i].GetLastTime() + delta);
m_donuts[i].SetTransformTime(m_donuts[i].GetTransformTime() + delta);
m_donuts[i].SetActorTime(m_donuts[i].GetActorTime() + delta);
m_donuts[i].SetUnknown0x158(m_donuts[i].GetUnknown0x158() + delta);
m_donuts[i].SetRotateTimeout(m_donuts[i].GetRotateTimeout() + delta);
}
}
@ -959,7 +959,7 @@ void Act3::Enable(MxBool p_enable)
InputManager()->SetWorld(this);
InputManager()->Register(this);
SetUserActor(m_copter);
m_copter->VTable0xa8();
m_copter->ApplyLocal2World();
SetAppCursor(e_cursorArrow);
}
}

View File

@ -878,7 +878,7 @@ void Isle::CheckAreaExiting()
case LegoGameState::e_vehicleExited: {
MxMatrix mat(UserActor()->GetROI()->GetLocal2World());
LegoPathBoundary* boundary = UserActor()->GetBoundary();
((IslePathActor*) UserActor())->VTable0xec(mat, boundary, TRUE);
((IslePathActor*) UserActor())->UpdateWorld(mat, boundary, TRUE);
break;
}
case LegoGameState::e_infocenterExited:

View File

@ -534,7 +534,7 @@ void LegoAct2::Enable(MxBool p_enable)
GameState()->SetActor(LegoActor::c_pepper);
m_pepper = FindROI("pepper");
((IslePathActor*) m_pepper->GetEntity())->VTable0xec(m_transformOnDisable, m_boundaryOnDisable, TRUE);
((IslePathActor*) m_pepper->GetEntity())->UpdateWorld(m_transformOnDisable, m_boundaryOnDisable, TRUE);
if (GameState()->m_previousArea == LegoGameState::e_infomain) {
GameState()->StopArea(LegoGameState::e_infomain);
@ -1209,19 +1209,19 @@ MxResult LegoAct2::InitializeShooting()
ap = (LegoLocomotionAnimPresenter*) Find("LegoAnimPresenter", "Ambul_Anim0");
assert(ap);
ap->FUN_1006d680(m_unk0x1138, 0.0f);
ap->CreateROIAndBuildMap(m_unk0x1138, 0.0f);
ap = (LegoLocomotionAnimPresenter*) Find("LegoAnimPresenter", "Ambul_Anim2");
assert(ap);
ap->FUN_1006d680(m_unk0x1138, 6.0f);
ap->CreateROIAndBuildMap(m_unk0x1138, 6.0f);
ap = (LegoLocomotionAnimPresenter*) Find("LegoAnimPresenter", "Ambul_Anim3");
assert(ap);
ap->FUN_1006d680(m_unk0x1138, 3.0f);
ap->CreateROIAndBuildMap(m_unk0x1138, 3.0f);
ap = (LegoLocomotionAnimPresenter*) Find("LegoAnimPresenter", "BrShoot");
assert(ap);
ap->FUN_1006d680(m_unk0x1138, -1.0f);
ap->CreateROIAndBuildMap(m_unk0x1138, -1.0f);
actor->SetWorldSpeed(0.0f);
m_unk0x1138->InitializeNextShot();

View File

@ -290,11 +290,11 @@ class LegoAnimNodeData : public LegoTreeNodeData {
// SIZE 0x08
struct LegoAnimActorEntry {
enum {
e_actorType2 = 2,
e_actorType3 = 3,
e_actorType4 = 4,
e_actorType5 = 5,
e_actorType6 = 6,
e_managedLegoActor = 2,
e_managedInvisibleRoiTrimmed = 3,
e_managedInvisibleRoi = 4,
e_sceneRoi1 = 5,
e_sceneRoi2 = 6,
};
LegoChar* m_name; // 0x00

View File

@ -37,7 +37,7 @@ class LegoWEGEdge : public LegoWEEdge {
c_bit1 = 0x01,
c_bit2 = 0x02,
c_bit3 = 0x04,
c_bit5 = 0x10
c_visible = 0x10
};
LegoWEGEdge();
@ -46,9 +46,9 @@ class LegoWEGEdge : public LegoWEEdge {
LegoS32 LinkEdgesAndFaces() override; // vtable+0x04
// FUNCTION: BETA10 0x100270c0
LegoU32 GetFlag0x10()
LegoU32 GetVisibility()
{
if (m_flags & c_bit5) {
if (m_flags & c_visible) {
return FALSE;
}
else {
@ -67,13 +67,13 @@ class LegoWEGEdge : public LegoWEEdge {
const LegoChar* GetName() { return m_name; }
// FUNCTION: BETA10 0x1005d5f0
void SetFlag0x10(LegoU32 p_disable)
void SetVisibility(LegoU32 p_disable)
{
if (p_disable) {
m_flags &= ~c_bit5;
m_flags &= ~c_visible;
}
else {
m_flags |= c_bit5;
m_flags |= c_visible;
}
}

View File

@ -0,0 +1,88 @@
#include "legospline.h"
#include "mxgeometry/mxmatrix.h"
DECOMP_SIZE_ASSERT(LegoSpline, 0x50)
// FUNCTION: LEGO1 0x1009a0f0
LegoSpline::LegoSpline()
{
for (LegoS32 i = 0; i < sizeOfArray(m_coefficents); i++) {
m_coefficents[i].Clear();
}
}
// FUNCTION: LEGO1 0x1009a130
LegoSpline::~LegoSpline()
{
}
// FUNCTION: LEGO1 0x1009a140
// FUNCTION: BETA10 0x10182c2f
void LegoSpline::SetSpline(
const Vector3& p_start,
const Vector3& p_tangentAtStart,
const Vector3& p_end,
const Vector3& p_tangentAtEnd
)
{
m_coefficents[0] = p_start;
m_coefficents[1] = p_tangentAtStart;
for (LegoS32 i = 0; i < 3; i++) {
m_coefficents[2][i] = (p_end[i] - p_start[i]) * 3.0f - p_tangentAtStart[i] * 2.0f - p_tangentAtEnd[i];
m_coefficents[3][i] = (p_start[i] - p_end[i]) * 2.0f + p_tangentAtEnd[i] + p_tangentAtStart[i];
}
}
// FUNCTION: LEGO1 0x1009a1e0
// FUNCTION: BETA10 0x10182d61
LegoResult LegoSpline::Evaluate(float p_alpha, Matrix4& p_mat, Vector3& p_up, LegoU32 p_reverse)
{
Vector3 position(p_mat[3]);
Vector3 right(p_mat[0]);
Vector3 up(p_mat[1]);
Vector3 dir(p_mat[2]);
if (isnan(p_alpha) || p_alpha <= 0.001) {
position = m_coefficents[0];
dir = m_coefficents[1];
}
else if (p_alpha >= 0.999) {
position = m_coefficents[0];
position += m_coefficents[1];
position += m_coefficents[2];
position += m_coefficents[3];
for (LegoS32 i = 0; i < 3; i++) {
dir[i] = m_coefficents[1][i] + m_coefficents[2][i] * 2.0f + m_coefficents[3][i] * 3.0f;
}
}
else {
float alpha_squared = p_alpha * p_alpha;
float alpha_cubed = alpha_squared * p_alpha;
for (LegoS32 i = 0; i < 3; i++) {
position[i] = m_coefficents[0][i] + m_coefficents[1][i] * p_alpha + m_coefficents[2][i] * alpha_squared +
m_coefficents[3][i] * alpha_cubed;
dir[i] =
m_coefficents[1][i] + m_coefficents[2][i] * p_alpha * 2.0f + m_coefficents[3][i] * alpha_squared * 3.0f;
}
}
if (p_reverse) {
dir *= -1.0f;
}
if (dir.Unitize() != 0) {
return FAILURE;
}
right.EqualsCross(p_up, dir);
if (right.Unitize() != 0) {
return FAILURE;
}
up.EqualsCross(dir, right);
return SUCCESS;
}

View File

@ -0,0 +1,27 @@
#ifndef __LEGOSPLINE_H
#define __LEGOSPLINE_H
#include "legotypes.h"
#include "mxgeometry/mxgeometry3d.h"
class Matrix4;
// SIZE 0x50
class LegoSpline {
public:
LegoSpline();
~LegoSpline();
void SetSpline(
const Vector3& p_start,
const Vector3& p_tangentAtStart,
const Vector3& p_end,
const Vector3& p_tangentAtEnd
);
LegoResult Evaluate(float p_alpha, Matrix4& p_mat, Vector3& p_v, LegoU32 p_reverse);
private:
Mx3DPointFloat m_coefficents[4]; // 0x00
};
#endif // __LEGOSPLINE_H

View File

@ -1,86 +0,0 @@
#include "legounknown.h"
#include "mxgeometry/mxmatrix.h"
DECOMP_SIZE_ASSERT(LegoUnknown, 0x50)
// FUNCTION: LEGO1 0x1009a0f0
LegoUnknown::LegoUnknown()
{
for (LegoS32 i = 0; i < sizeOfArray(m_unk0x00); i++) {
m_unk0x00[i].Clear();
}
}
// FUNCTION: LEGO1 0x1009a130
LegoUnknown::~LegoUnknown()
{
}
// FUNCTION: LEGO1 0x1009a140
// FUNCTION: BETA10 0x10182c2f
void LegoUnknown::FUN_1009a140(
const Vector3& p_point1,
const Vector3& p_point2,
const Vector3& p_point3,
const Vector3& p_point4
)
{
m_unk0x00[0] = p_point1;
m_unk0x00[1] = p_point2;
for (LegoS32 i = 0; i < 3; i++) {
m_unk0x00[2][i] = (p_point3[i] - p_point1[i]) * 3.0f - p_point2[i] * 2.0f - p_point4[i];
m_unk0x00[3][i] = (p_point1[i] - p_point3[i]) * 2.0f + p_point4[i] + p_point2[i];
}
}
// FUNCTION: LEGO1 0x1009a1e0
// FUNCTION: BETA10 0x10182d61
LegoResult LegoUnknown::FUN_1009a1e0(float p_f1, Matrix4& p_mat, Vector3& p_v, LegoU32 p_und)
{
Vector3 v1(p_mat[3]);
Vector3 v2(p_mat[0]);
Vector3 v3(p_mat[1]);
Vector3 v4(p_mat[2]);
if (isnan(p_f1) || p_f1 <= 0.001) {
v1 = m_unk0x00[0];
v4 = m_unk0x00[1];
}
else if (p_f1 >= 0.999) {
v1 = m_unk0x00[0];
v1 += m_unk0x00[1];
v1 += m_unk0x00[2];
v1 += m_unk0x00[3];
for (LegoS32 i = 0; i < 3; i++) {
v4[i] = m_unk0x00[1][i] + m_unk0x00[2][i] * 2.0f + m_unk0x00[3][i] * 3.0f;
}
}
else {
float local30 = p_f1 * p_f1;
float local34 = local30 * p_f1;
for (LegoS32 i = 0; i < 3; i++) {
v1[i] = m_unk0x00[0][i] + m_unk0x00[1][i] * p_f1 + m_unk0x00[2][i] * local30 + m_unk0x00[3][i] * local34;
v4[i] = m_unk0x00[1][i] + m_unk0x00[2][i] * p_f1 * 2.0f + m_unk0x00[3][i] * local30 * 3.0f;
}
}
if (p_und) {
v4 *= -1.0f;
}
if (v4.Unitize() != 0) {
return FAILURE;
}
v2.EqualsCross(p_v, v4);
if (v2.Unitize() != 0) {
return FAILURE;
}
v3.EqualsCross(v4, v2);
return SUCCESS;
}

View File

@ -1,27 +0,0 @@
#ifndef __LEGOUNKNOWN_H
#define __LEGOUNKNOWN_H
#include "legotypes.h"
#include "mxgeometry/mxgeometry3d.h"
class Matrix4;
// SIZE 0x50
class LegoUnknown {
public:
LegoUnknown();
~LegoUnknown();
void FUN_1009a140(
const Vector3& p_point1,
const Vector3& p_point2,
const Vector3& p_point3,
const Vector3& p_point4
);
LegoResult FUN_1009a1e0(float p_f1, Matrix4& p_mat, Vector3& p_v, LegoU32 p_und);
private:
Mx3DPointFloat m_unk0x00[4]; // 0x00
};
#endif // __LEGOUNKNOWN_H

View File

@ -163,11 +163,11 @@
#include "lego/sources/geom/legowegedge.h"
#include "lego/sources/misc/legocontainer.h"
#include "lego/sources/misc/legoimage.h"
#include "lego/sources/misc/legospline.h"
#include "lego/sources/misc/legostorage.h"
#include "lego/sources/misc/legotexture.h"
#include "lego/sources/misc/legotree.h"
#include "lego/sources/misc/legotypes.h"
#include "lego/sources/misc/legounknown.h"
#include "lego/sources/misc/legoutil.h"
#include "lego/sources/misc/version.h"
#include "lego/sources/roi/legolod.h"

View File

@ -43,15 +43,15 @@ class MxCompositePresenter : public MxPresenter {
void SetTickleState(TickleState p_tickleState) override; // vtable+0x44
MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48
void Enable(MxBool p_enable) override; // vtable+0x54
virtual void VTable0x58(MxEndActionNotificationParam& p_param); // vtable+0x58
virtual void VTable0x5c(MxNotificationParam& p_param); // vtable+0x5c
virtual void VTable0x60(MxPresenter* p_presenter); // vtable+0x60
virtual void HandleEndAction(MxEndActionNotificationParam& p_param); // vtable+0x58
virtual void HandlePresenter(MxNotificationParam& p_param); // vtable+0x5c
virtual void AdvanceSerialAction(MxPresenter* p_presenter); // vtable+0x60
// FUNCTION: LEGO1 0x1000caf0
virtual MxBool VTable0x64(undefined4 p_undefined)
virtual MxBool GetActionEnded(undefined4 p_undefined)
{
if (m_compositePresenter) {
return m_compositePresenter->VTable0x64(p_undefined);
return m_compositePresenter->GetActionEnded(p_undefined);
}
return TRUE;
} // vtable+0x64

View File

@ -62,7 +62,7 @@ class MxVideoManager : public MxPresentationManager {
LPDIRECT3D2 m_pDirect3D; // 0x54
MxDisplaySurface* m_displaySurface; // 0x58
MxRegion* m_region; // 0x5c
MxBool m_unk0x60; // 0x60
MxBool m_created; // 0x60
};
#endif // MXVIDEOMANAGER_H

View File

@ -117,10 +117,10 @@ MxLong MxCompositePresenter::Notify(MxParam& p_param)
switch (param.GetNotification()) {
case c_notificationEndAction:
VTable0x58((MxEndActionNotificationParam&) p_param);
HandleEndAction((MxEndActionNotificationParam&) p_param);
break;
case c_notificationPresenter:
VTable0x5c((MxNotificationParam&) p_param);
HandlePresenter((MxNotificationParam&) p_param);
break;
default:
assert(0);
@ -131,7 +131,7 @@ MxLong MxCompositePresenter::Notify(MxParam& p_param)
}
// FUNCTION: LEGO1 0x100b67f0
void MxCompositePresenter::VTable0x58(MxEndActionNotificationParam& p_param)
void MxCompositePresenter::HandleEndAction(MxEndActionNotificationParam& p_param)
{
MxPresenter* presenter = (MxPresenter*) p_param.GetSender();
MxDSAction* action = p_param.GetAction();
@ -177,7 +177,7 @@ void MxCompositePresenter::VTable0x58(MxEndActionNotificationParam& p_param)
}
// FUNCTION: LEGO1 0x100b69b0
void MxCompositePresenter::VTable0x5c(MxNotificationParam& p_param)
void MxCompositePresenter::HandlePresenter(MxNotificationParam& p_param)
{
if (!m_list.empty()) {
MxPresenter* presenter = (MxPresenter*) p_param.GetSender();
@ -218,13 +218,13 @@ void MxCompositePresenter::VTable0x5c(MxNotificationParam& p_param)
}
// FUNCTION: LEGO1 0x100b6b40
void MxCompositePresenter::VTable0x60(MxPresenter* p_presenter)
void MxCompositePresenter::AdvanceSerialAction(MxPresenter* p_presenter)
{
for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) {
if (*it == p_presenter) {
if (++it == m_list.end()) {
if (m_compositePresenter) {
m_compositePresenter->VTable0x60(this);
m_compositePresenter->AdvanceSerialAction(this);
}
}
else if (m_action->IsA("MxDSSerialAction")) {

View File

@ -156,7 +156,8 @@ void MxMediaPresenter::EndAction()
m_currentChunk = NULL;
if (m_action->GetFlags() & MxDSAction::c_world && (!m_compositePresenter || !m_compositePresenter->VTable0x64(2))) {
if (m_action->GetFlags() & MxDSAction::c_world &&
(!m_compositePresenter || !m_compositePresenter->GetActionEnded(2))) {
MxPresenter::Enable(FALSE);
SetTickleState(e_idle);
}

View File

@ -134,7 +134,7 @@ void MxStillPresenter::StreamingTickle()
ProgressTickleState(e_repeating);
if (m_action->GetDuration() == -1 && m_compositePresenter) {
m_compositePresenter->VTable0x60(this);
m_compositePresenter->AdvanceSerialAction(this);
}
}
}

View File

@ -43,7 +43,7 @@ MxResult MxVideoManager::Init()
m_displaySurface = NULL;
m_region = NULL;
m_videoParam.SetPalette(NULL);
m_unk0x60 = FALSE;
m_created = FALSE;
return SUCCESS;
}
@ -73,7 +73,7 @@ void MxVideoManager::Destroy(MxBool p_fromDestructor)
delete m_videoParam.GetPalette();
}
if (m_unk0x60) {
if (m_created) {
if (m_pDirectDraw) {
m_pDirectDraw->Release();
}
@ -154,7 +154,7 @@ MxResult MxVideoManager::VTable0x28(
MxBool locked = FALSE;
MxResult status = FAILURE;
m_unk0x60 = FALSE;
m_created = FALSE;
if (MxPresentationManager::Create() != SUCCESS) {
goto done;
@ -229,7 +229,7 @@ MxResult MxVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS,
MxResult status = FAILURE;
HWND hWnd = NULL;
m_unk0x60 = TRUE;
m_created = TRUE;
if (MxPresentationManager::Create() != SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "MxPresentationManager::Create failed");

View File

@ -123,7 +123,7 @@ class Vector4 : public Vector3 {
Vector4(float* p_data) : Vector3(p_data) {}
// Some code initializes a Vector4 from a `const float*` source.
// Example: `LegoCarBuild::VTable0x6c`
// Example: `LegoCarBuild::CheckIntersections`
// Vector4 however is a class that can mutate its underlying source, making
// initialization with a const source fundamentally incompatible.
// BETA10 appears to have two separate constructors for Vector4 as well,

63
docs/README.md Normal file
View File

@ -0,0 +1,63 @@
# LEGO Island File Format Documentation
This folder contains documentation for LEGO Island's custom binary file formats using [Kaitai Struct](https://kaitai.io/), a declarative language for describing binary data structures.
## What is Kaitai Struct?
Kaitai Struct allows you to define binary formats in a YAML-based `.ksy` file, which can then be:
- Compiled into parser libraries for [many programming languages](https://kaitai.io/#quick-start) (C++, Python, JavaScript, etc.)
- Visualized interactively using the [Kaitai Struct Visualizer](https://github.com/kaitai-io/kaitai_struct_visualizer)
- Dumped to human-readable formats using `ksdump`
<img width="1877" height="706" alt="image" src="https://github.com/user-attachments/assets/0d124219-1208-48ce-83bb-f433d9bb84b1" />
## Documented Formats
| File | Extension | Description |
|------|-----------|-------------|
| [`savegame.ksy`](/docs/savegame.ksy) | `.GS` | Main game save data (game state, progress, customizations) |
| [`players.ksy`](/docs/players.ksy) | `.gsi` | Player profile save data (usernames) |
| [`history.ksy`](/docs/history.ksy) | `.gsi` | Score history and high scores |
## Using the Tools
### Installation
See the [Kaitai Struct Visualizer installation instructions](https://github.com/kaitai-io/kaitai_struct_visualizer?tab=readme-ov-file#downloading-and-installing) for setup details.
### Kaitai Struct Visualizer (ksv)
The [Kaitai Struct Visualizer](https://github.com/kaitai-io/kaitai_struct_visualizer) (`ksv`) provides an interactive terminal UI for exploring binary files.
```bash
# View a save game file
ksv samples/G0.GS savegame.ksy
# View a Players.gsi file
ksv samples/Players.gsi players.ksy
# View a History.gsi file
ksv samples/History.gsi history.ksy
```
### Kaitai Struct Dump (ksdump)
`ksdump` outputs the parsed structure as JSON or YAML for scripting and inspection.
```bash
# Dump a save game to JSON
ksdump --format json samples/G0.GS savegame.ksy
# Dump Players.gsi to JSON
ksdump --format json samples/Players.gsi players.ksy
# Dump History.gsi to YAML
ksdump --format yaml samples/History.gsi history.ksy
```
## Sample Files
The [`samples/`](/docs/samples/) directory contains example save files for testing:
- `G0.GS`, `G1.GS`, `G2.GS` - Sample main game save files (slots 0, 1, 2)
- `Players.gsi` - Sample player profile data
- `History.gsi` - Sample score history data

125
docs/history.ksy Normal file
View File

@ -0,0 +1,125 @@
meta:
id: history
title: Score History Save File
application: LEGO Island
file-extension: gsi
license: CC0-1.0
endian: le
doc: |
Score history save data for LEGO Island (1997). Stores up to 20 player
score entries, tracking high scores across all missions and characters.
The file is located at `<save_path>/History.gsi` where save_path is
typically the game's installation directory.
seq:
- id: next_player_id
type: s2
doc: |
The next player ID to be assigned when a new player profile is created.
Increments each time a new player is added, ensuring unique IDs.
- id: count
type: s2
doc: Number of score entries in the history (0-20 max).
- id: entries
type: score_entry
repeat: expr
repeat-expr: count
doc: Array of score history entries, sorted by total score descending.
types:
score_entry:
doc: |
A single score history entry containing a player's high scores across
all minigames and characters. Total serialized size is 45 bytes
(2 for index + 43 for score_item data).
seq:
- id: index
type: s2
doc: Array index of this entry (0 to count-1). Stored redundantly in file.
- id: total_score
type: s2
doc: Sum of all individual high scores across all missions and actors.
- id: scores
type: mission_scores
doc: High scores organized by mission type, each containing scores per actor.
- id: name
type: username
doc: The player's username associated with these scores.
- id: player_id
type: s2
doc: Unique player identifier matching the player's profile.
mission_scores:
doc: |
High scores for all 5 missions. Each mission contains scores for all
5 playable actors.
seq:
- id: car_race
type: actor_scores
doc: Car Race mission high scores.
- id: jetski_race
type: actor_scores
doc: Jetski Race mission high scores.
- id: pizza_delivery
type: actor_scores
doc: Pizza Delivery mission high scores.
- id: tow_track
type: actor_scores
doc: Tow Track mission high scores.
- id: ambulance
type: actor_scores
doc: Ambulance mission high scores.
actor_scores:
doc: |
High scores for a single mission across all 5 playable actors.
seq:
- id: pepper
type: u1
enum: score_color
doc: High score for Pepper.
- id: mama
type: u1
enum: score_color
doc: High score for Mama.
- id: papa
type: u1
enum: score_color
doc: High score for Papa.
- id: nick
type: u1
enum: score_color
doc: High score for Nick.
- id: laura
type: u1
enum: score_color
doc: High score for Laura.
username:
doc: |
A player username consisting of up to 7 letters. Each letter is stored
as a signed 16-bit index. The struct is always 14 bytes (0x0e).
seq:
- id: letters
type: s2
repeat: expr
repeat-expr: 7
doc: |
Letter indices for the username characters:
- 0-25: Standard alphabet (0=A, 1=B, ..., 25=Z)
- 29: International ä, å, or ñ (language-dependent)
- 30: International ö or æ (language-dependent)
- 31: International ß or ø (language-dependent)
- 32: International ü
- -1 (0xFFFF): Empty/unused position
Unused positions are filled with -1. A name shorter than 7
characters will have trailing -1 values.
enums:
score_color:
0: grey
1: yellow
2: blue
3: red

48
docs/players.ksy Normal file
View File

@ -0,0 +1,48 @@
meta:
id: players
title: Players Save File
application: LEGO Island
file-extension: gsi
license: CC0-1.0
endian: le
doc: |
Player profile save data for LEGO Island (1997). Stores up to 9 player
profiles, each identified by a 7-character username. Usernames are stored
as letter indices rather than ASCII characters.
The file is located at `<save_path>/Players.gsi` where save_path is
typically the game's installation directory.
seq:
- id: count
type: s2
doc: |
Number of saved player profiles. The game supports a maximum of 9
players; when a 10th player is added, the oldest profile is deleted.
- id: entries
type: username
repeat: expr
repeat-expr: count
doc: Array of player username entries, ordered by most recently played.
types:
username:
doc: |
A player username consisting of up to 7 letters. Each letter is stored
as a signed 16-bit index. The struct is always 14 bytes (0x0e).
seq:
- id: letters
type: s2
repeat: expr
repeat-expr: 7
doc: |
Letter indices for the username characters:
- 0-25: Standard alphabet (0=A, 1=B, ..., 25=Z)
- 29: International ä, å, or ñ (language-dependent)
- 30: International ö or æ (language-dependent)
- 31: International ß or ø (language-dependent)
- 32: International ü
- -1 (0xFFFF): Empty/unused position
Unused positions are filled with -1. A name shorter than 7
characters will have trailing -1 values.

BIN
docs/samples/G0.GS Executable file

Binary file not shown.

BIN
docs/samples/G1.GS Executable file

Binary file not shown.

BIN
docs/samples/G2.GS Executable file

Binary file not shown.

BIN
docs/samples/History.gsi Executable file

Binary file not shown.

BIN
docs/samples/Players.gsi Executable file

Binary file not shown.

1014
docs/savegame.ksy Normal file

File diff suppressed because it is too large Load Diff