Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding TempVisualEffectAPI #313

Merged
merged 5 commits into from
Dec 14, 2021
Merged

Conversation

Vale-X
Copy link
Contributor

@Vale-X Vale-X commented Nov 25, 2021

Allows for adding custom TemporaryVisualEffects (TVEs) to every CharacterBody spawned that functions the same as vanilla TVEs.

Use TempVisualEffectAPI.AddTemporaryVisualEffect() before WhenContentPackLoaded (usually in mod's Awake()) to add a custom TVE to a static List and Dictionary. Custom TVE list is copied into R2APITVEController components which are added on CharacterBody.onBodyStartGlobal. Hooks onto CharacterBody's UpdateAllTemporaryVisualEffects() and UpdateSingleTemporaryVisualEffect() to update custom TVEs just like vanilla ones. Compares the latter method's resourceString input with the dictionary's string key in order to instantiate the correct TVE GameObject.

AddTemporaryVisualEffect() requires a CharacterBody input, bool output delegate parameter. This delegate is used for the 'active' of the TVE - if it returns true, the TVE will be created/activated for the instance.

Example use:
2vkS6zR

Allows for adding custom TemporaryVisualEffects (TVEs) to every CharacterBody spawned that functions the same as vanilla TVEs.

Use `TempVisualEffectAPI.AddTemporaryVisualEffect()` before `WhenContentPackLoaded` to add a custom TVE to a static List and Dictionary. Custom TVE list is copied into `R2APITVEController` components which are added on `CharacterBody.onBodyStartGlobal`. Hooks onto CharacterBody's `UpdateAllTemporaryVisualEffects()` and `UpdateSingleTemporaryVisualEffect` to update custom TVEs just like vanilla ones. Compares the latter method's `resourceString` input with the dictionary's string key in order to instantiate the correct TVE GameObject.

`AddTemporaryVisualEffect()` requires a CharacterBody input, bool output delegate parameter. This delegate is used for the 'active' of the TVE - if it returns true, the TVE will be created/activated for the instance.
if (controller) {
for (int i = 0; i < controller.localTVEs.Count; i++) {
TempVisualEffectAPI.TemporaryVisualEffectStruct temp = controller.localTVEs[i];
self.UpdateSingleTemporaryVisualEffect(ref temp.effect, moddedString + temp.effectPrefab.name, temp.useBestFitRadius ? self.radius : self.bestFitRadius, temp.condition.Invoke(self), temp.childLocatorOverride);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use effectName not .name so that garbage isnt generated each frame

private static void UpdateSingleHook(ILContext il) {
var cursor = new ILCursor(il);

GameObject GetCustomTVE(GameObject vanillaLoaded, string ResourceString)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resourceString not ResourceString

var newTVE = new TemporaryVisualEffectStruct();

if (effectPrefab == null) {
R2API.Logger.LogError($"Tried to add TVE: {effectPrefab.name} GameObject is null"); return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.name will fail here since ref is null

newTVE.effectName = effectPrefab.name;

tves.Add(newTVE);
tveDict.Add(moddedString + effectPrefab.name, newTVE);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

effectName not .name


internal static List<TemporaryVisualEffectStruct> tves = new List<TemporaryVisualEffectStruct>();
internal static Dictionary<string, TemporaryVisualEffectStruct> tveDict = new Dictionary<string, TemporaryVisualEffectStruct>();
internal static readonly string moddedString = "R2APIModded:";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal const string

Fixed based on the Pull Request review from `xiaoxiao921`. Thank you for the review and suggesting changes! I've implemented the suggested changes and some extras:

- Reorganised the checks, such as checking if the effectPrefab is null first.
- `GameObject == null` now throws NRE instead of returns false.
- Removed `effect.effectPrefab == effectPrefab` check. Matching GameObjects can be added, as long as the name is different (For using the same effect but in a different radius, condition, or child locator).
- Changed 'Tried' to 'Failed'. More accurate.
Vale-X and others added 2 commits November 29, 2021 01:36
Updated `useBestFitRadius` to default to false, making `effectPrefab` and `condition` the only required parameters.
Whoops, had the API named wrong.
@tristanmcpherson tristanmcpherson merged commit 394b6e2 into risk-of-thunder:master Dec 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants