Open xAstroBoy opened 4 months ago
@winstxnhdw looks solid to me, i have been testing these past 3 hours and got this custom camera to work and preserve hud and the rest, enemies work properly when they go outside, and best of all spider now follows the controller .
@winstxnhdw with the jester i had to add a new Event , OnPlayerCollision , because for some weird reason the jester wouldn't kill a player if outside, so i fixed that.
EDIT : i checked the other enemies that are inside and replicated their collision system without a check to make sure they work
Make sure to add this to the InputListener:
internal static event Action<bool>? OnLeftAltButtonHold;
InputListener.OnLeftAltButtonHold?.Invoke(Keyboard.current[Key.LeftAlt].isPressed);
using System;
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
using UnityEngine.AI;
using GameNetcodeStuff;
using Hax;
internal sealed class PossessionMod : MonoBehaviour {
const float TeleportDoorCooldown = 2.5f;
const float DoorInteractionCooldown = 0.7f;
bool IsLeftAltHeld { get; set; } = false;
internal static PossessionMod? Instance { get; private set; }
internal bool IsPossessed => this.Possession.IsPossessed;
internal EnemyAI? PossessedEnemy => this.Possession.Enemy;
Possession Possession { get; } = new();
GameObject? CharacterMovementInstance { get; set; } = null;
CharacterMovement? CharacterMovement { get; set; } = null;
MousePan? MousePan { get; set; } = null;
bool FirstUpdate { get; set; } = true;
bool NoClipEnabled { get; set; } = false;
bool IsAIControlled { get; set; } = false;
Dictionary<Type, IController> EnemyControllers { get; } = new() {
{ typeof(CentipedeAI), new SnareFleaController() },
{ typeof(FlowermanAI), new BrackenController() },
{ typeof(ForestGiantAI), new ForestGiantController() },
{ typeof(HoarderBugAI), new HoardingBugController() },
{ typeof(JesterAI), new JesterController() },
{ typeof(NutcrackerEnemyAI), new NutcrackerController() },
{ typeof(PufferAI), new SporeLizardController() },
{ typeof(BaboonBirdAI), new BaboonHawkController() },
{ typeof(SandWormAI), new EarthLeviathanController() },
{ typeof(MouthDogAI), new EyelessDogController() },
{ typeof(MaskedPlayerEnemy), new MaskedPlayerController() },
{ typeof(SpringManAI), new CoilHeadController() },
{ typeof(BlobAI), new HygrodereController() },
{ typeof(TestEnemy), new TestEnemyController() },
{ typeof(LassoManAI), new LassoManController() },
{ typeof(CrawlerAI), new CrawlerController() },
{ typeof(SandSpiderAI), new SandSpiderController() },
{ typeof(RedLocustBees), new CircuitBeesController() }
};
float DoorCooldownRemaining { get; set; } = 0.0f;
float TeleportCooldownRemaining { get; set; } = 0.0f;
EntranceTeleport? MainEntrance { get; set; }
void Awake() {
this.InitCharacterMovement();
this.MousePan = this.gameObject.AddComponent<MousePan>();
this.enabled = false;
PossessionMod.Instance = this;
}
void InitCharacterMovement(EnemyAI? enemy = null) {
this.CharacterMovementInstance = new GameObject("Hax CharacterMovement");
this.CharacterMovementInstance.transform.position = enemy is null ? default : enemy.transform.position;
this.CharacterMovement = this.CharacterMovementInstance.AddComponent<CharacterMovement>();
this.CharacterMovement.Init();
if (enemy is not null) {
this.CharacterMovement.CalibrateCollision(enemy);
this.CharacterMovement.CharacterSprintSpeed = this.SprintMultiplier(enemy);
}
}
void OnEnable() {
InputListener.OnNPress += this.ToggleNoClip;
InputListener.OnZPress += this.Unpossess;
InputListener.OnLeftButtonPress += this.UsePrimarySkill;
InputListener.OnRightButtonPress += this.UseSecondarySkill;
InputListener.OnRightButtonRelease += this.ReleaseSecondarySkill;
InputListener.OnRightButtonHold += this.OnRightMouseButtonHold;
InputListener.OnDelPress += this.KillEnemyAndUnposses;
InputListener.OnF9Press += this.ToggleAIControl;
InputListener.OnLeftAltButtonHold += this.HoldAlt;
this.UpdateComponentsOnCurrentState(true);
}
void OnDisable() {
InputListener.OnNPress -= this.ToggleNoClip;
InputListener.OnZPress -= this.Unpossess;
InputListener.OnLeftButtonPress -= this.UsePrimarySkill;
InputListener.OnRightButtonPress -= this.UseSecondarySkill;
InputListener.OnRightButtonRelease -= this.ReleaseSecondarySkill;
InputListener.OnRightButtonHold -= this.OnRightMouseButtonHold;
InputListener.OnDelPress -= this.KillEnemyAndUnposses;
InputListener.OnF9Press -= this.ToggleAIControl;
InputListener.OnLeftAltButtonHold -= this.HoldAlt;
this.UpdateComponentsOnCurrentState(false);
}
void HoldAlt(bool isHeld) => this.IsLeftAltHeld = isHeld;
void OnRightMouseButtonHold(bool isPressed) {
if (isPressed) {
this.OnSecondarySkillHold();
}
}
void SendPossessionNotifcation(string message) {
Helper.SendNotification(
title: "Possession",
body: message
);
}
void ToggleNoClip() {
this.NoClipEnabled = !this.NoClipEnabled;
this.UpdateComponentsOnCurrentState(this.enabled);
this.SendPossessionNotifcation($"NoClip: {(this.NoClipEnabled ? "Enabled" : "Disabled")}");
}
void UpdateComponentsOnCurrentState(bool thisGameObjectIsEnabled) {
if (this.MousePan is null) return;
this.MousePan.enabled = thisGameObjectIsEnabled;
this.CharacterMovement?.gameObject.SetActive(thisGameObjectIsEnabled);
this.CharacterMovement?.SetNoClipMode(this.NoClipEnabled);
}
void Update() {
if (Helper.CurrentCamera is not Camera { enabled: true } camera) return;
if (Helper.LocalPlayer is not PlayerControllerB localPlayer) return;
if (this.CharacterMovement is not CharacterMovement characterMovement) return;
if (this.Possession.Enemy is not EnemyAI enemy) return;
if (enemy.agent is not NavMeshAgent agent) return;
this.DoorCooldownRemaining = Mathf.Clamp(
this.DoorCooldownRemaining - Time.deltaTime,
0.0f,
PossessionMod.DoorInteractionCooldown
);
this.TeleportCooldownRemaining = Mathf.Clamp(
this.TeleportCooldownRemaining - Time.deltaTime,
0.0f,
PossessionMod.TeleportDoorCooldown
);
enemy.ChangeEnemyOwnerServerRpc(localPlayer.actualClientId);
this.UpdateCameraPosition(camera, enemy);
this.UpdateCameraRotation(camera, enemy);
if (this.FirstUpdate) {
this.FirstUpdate = false;
this.InitCharacterMovement(enemy);
this.UpdateComponentsOnCurrentState(true);
this.SetAIControl(false);
this.MainEntrance = RoundManager.FindMainEntranceScript(false);
}
if (!this.EnemyControllers.TryGetValue(enemy.GetType(), out IController controller)) {
if (!this.IsAIControlled) {
this.UpdateEnemyPosition(enemy);
this.UpdateEnemyRotation();
}
if (this.MainEntrance != null) {
_ = enemy.SetOutsideStatus(enemy.transform.position.y > this.MainEntrance.transform.position.y + 5.0f);
}
if (enemy.isEnemyDead) {
this.Unpossess();
}
this.InteractWithAmbient(enemy, null);
return;
}
if (this.MainEntrance != null) {
if (enemy.SetOutsideStatus(enemy.transform.position.y > this.MainEntrance.transform.position.y + 5.0f)) {
controller.OnOutsideStatusChange(enemy);
enemy.FinishedCurrentSearchRoutine();
}
}
if (enemy.isEnemyDead) {
controller.OnDeath(enemy);
this.Unpossess();
}
controller.Update(enemy, this.IsAIControlled);
this.InteractWithAmbient(enemy, controller);
localPlayer.cursorTip.text = controller.GetPrimarySkillName(enemy);
if (this.IsAIControlled) {
return;
}
if (!controller.IsAbleToMove(enemy)) {
return;
}
if (controller.SyncAnimationSpeedEnabled(enemy)) {
characterMovement.CharacterSpeed = agent.speed;
}
if (controller.IsAbleToRotate(enemy)) {
this.UpdateEnemyRotation();
}
this.UpdateEnemyPosition(enemy);
controller.OnMovement(enemy, this.CharacterMovement.IsMoving, this.CharacterMovement.IsSprinting);
}
void UpdateCameraPosition(Camera camera, EnemyAI enemy) {
Vector3 newPosition = enemy.transform.position + (0.0f * (Vector3.up - enemy.transform.forward));
camera.transform.position = newPosition;
}
void UpdateCameraRotation(Camera camera, EnemyAI enemy) {
Quaternion newRotation = !this.IsAIControlled
? this.transform.rotation
: Quaternion.LookRotation(enemy.transform.forward);
// Set the camera rotation without changing its position
camera.transform.rotation = newRotation;
// Calculate the new camera position based on the updated rotation
Vector3 offset = 2.5f * (Vector3.up - camera.transform.forward);
camera.transform.position = enemy.transform.position + offset;
}
void UpdateEnemyRotation() {
if (this.CharacterMovement is not CharacterMovement characterMovement) return;
if (!this.IsLeftAltHeld) {
// Only take the horizontal rotation
Quaternion horizontalRotation = Quaternion.Euler(0f, this.transform.eulerAngles.y, 0f);
characterMovement.transform.rotation = horizontalRotation;
}
}
// Updates enemy's position to match the possessed object's position
void UpdateEnemyPosition(EnemyAI enemy) {
if (this.CharacterMovement is not CharacterMovement characterMovement) return;
Vector3 enemyEuler = enemy.transform.eulerAngles;
enemyEuler.y = this.transform.eulerAngles.y;
enemy.transform.position = characterMovement.transform.position;
if (!this.IsLeftAltHeld) {
enemy.transform.eulerAngles = enemyEuler;
}
}
// Possesses the specified enemy
internal void Possess(EnemyAI enemy) {
if (enemy.isEnemyDead) return;
this.Unpossess();
this.FirstUpdate = true;
this.Possession.SetEnemy(enemy);
this.IsAIControlled = false;
this.TeleportCooldownRemaining = 0.0f;
this.DoorCooldownRemaining = 0.0f;
if (this.EnemyControllers.TryGetValue(enemy.GetType(), out IController controller)) {
controller.OnPossess(enemy);
}
}
void KillEnemyAndUnposses() {
if (Helper.LocalPlayer is not PlayerControllerB localPlayer) return;
if (this.Possession.Enemy is not EnemyAI enemy) return;
enemy.Kill(localPlayer.actualClientId);
if (localPlayer.IsHost) {
if (enemy.TryGetComponent(out NetworkObject networkObject)) {
networkObject.Despawn(true);
}
}
this.Unpossess();
}
// Releases possession of the current enemy
internal void Unpossess() {
if (this.Possession.Enemy is not EnemyAI enemy) return;
if (enemy.agent is NavMeshAgent agent) {
agent.updatePosition = true;
agent.updateRotation = true;
agent.isStopped = false;
this.UpdateEnemyPosition(enemy);
_ = enemy.agent.Warp(enemy.transform.position);
enemy.SyncPositionToClients();
}
if (this.EnemyControllers.TryGetValue(enemy.GetType(), out IController controller)) {
controller.OnUnpossess(enemy);
}
this.IsAIControlled = false;
this.MainEntrance = null;
this.Possession.Clear();
if (this.CharacterMovement is not null) {
Destroy(this.CharacterMovementInstance);
this.CharacterMovementInstance = null;
}
}
void ToggleAIControl() {
if (this.Possession.Enemy?.agent is null) return;
if (this.CharacterMovement is null) return;
if (this.MousePan is null) return;
this.IsAIControlled = !this.IsAIControlled;
this.SetAIControl(this.IsAIControlled);
this.SendPossessionNotifcation($"AI Control: {(this.IsAIControlled ? "Enabled" : "Disabled")}");
}
void SetAIControl(bool enableAI) {
if (this.CharacterMovement is not CharacterMovement characterMovement) return;
if (this.Possession.Enemy is not EnemyAI enemy) return;
if (enemy.agent is not NavMeshAgent agent) return;
if (enableAI) {
_ = enemy.agent.Warp(enemy.transform.position);
enemy.SyncPositionToClients();
}
if (this.NoClipEnabled) {
this.NoClipEnabled = false;
characterMovement.SetNoClipMode(false);
}
agent.updatePosition = enableAI;
agent.updateRotation = enableAI;
agent.isStopped = !enableAI;
characterMovement.SetPosition(enemy.transform.position);
characterMovement.enabled = !enableAI;
}
void HandleEntranceDoors(EnemyAI enemy, RaycastHit hit, IController controller) {
if (this.TeleportCooldownRemaining > 0.0f) return;
if (!hit.collider.gameObject.TryGetComponent(out EntranceTeleport entrance)) return;
this.InteractWithTeleport(enemy, entrance, controller);
this.TeleportCooldownRemaining = PossessionMod.TeleportDoorCooldown;
}
void HandleEnemyPlayerInteraction(EnemyAI enemy, RaycastHit hit, IController controller) {
if (controller == null) return;
if (!hit.collider.gameObject.TryGetComponent(out PlayerControllerB player)) return;
if (player.IsDead()) return;
controller.OnCollideWithPlayer(enemy, player);
}
float InteractRange(EnemyAI enemy) =>
this.EnemyControllers.TryGetValue(enemy.GetType(), out IController value)
? value.InteractRange(enemy)
: IController.DefaultInteractRange;
float SprintMultiplier(EnemyAI enemy) =>
this.EnemyControllers.TryGetValue(enemy.GetType(), out IController value)
? value.SprintMultiplier(enemy)
: IController.DefaultSprintMultiplier;
void InteractWithAmbient(EnemyAI enemy, IController? controller) {
if (!Physics.Raycast(enemy.transform.position, enemy.transform.forward, out RaycastHit hit,
this.InteractRange(enemy))) return;
if (hit.collider.gameObject.TryGetComponent(out DoorLock doorLock) && this.DoorCooldownRemaining <= 0.0f) {
this.OpenDoorAsEnemy(doorLock);
this.DoorCooldownRemaining = PossessionMod.DoorInteractionCooldown;
return;
}
if (controller != null) {
if (controller.CanUseEntranceDoors(enemy)) {
this.HandleEntranceDoors(enemy, hit, controller);
return;
}
this.HandleEnemyPlayerInteraction(enemy, hit, controller);
}
}
void OpenDoorAsEnemy(DoorLock door) {
if (door.Reflect().GetInternalField<bool>("isDoorOpened")) return;
if (door.gameObject.TryGetComponent(out AnimatedObjectTrigger trigger)) {
trigger.TriggerAnimationNonPlayer(false, true, false);
}
door.OpenDoorAsEnemyServerRpc();
}
Transform? GetExitPointFromDoor(EntranceTeleport entrance) =>
Helper.FindObjects<EntranceTeleport>().First(teleport =>
teleport.entranceId == entrance.entranceId && teleport.isEntranceToBuilding != entrance.isEntranceToBuilding
)?.entrancePoint;
void InteractWithTeleport(EnemyAI enemy, EntranceTeleport teleport, IController controller) {
if (this.CharacterMovement is not CharacterMovement characterMovement) return;
if (this.GetExitPointFromDoor(teleport) is not Transform exitPoint) return;
characterMovement.SetPosition(exitPoint.position);
_ = enemy.SetOutsideStatus(!teleport.isEntranceToBuilding);
controller.OnOutsideStatusChange(enemy);
}
void UsePrimarySkill() {
if (this.Possession.Enemy is not EnemyAI enemy) return;
if (!this.EnemyControllers.TryGetValue(enemy.GetType(), out IController controller)) return;
controller.UsePrimarySkill(enemy);
}
void UseSecondarySkill() {
if (this.Possession.Enemy is not EnemyAI enemy) return;
if (!this.EnemyControllers.TryGetValue(enemy.GetType(), out IController controller)) return;
controller.UseSecondarySkill(enemy);
}
void OnSecondarySkillHold() {
if (this.Possession.Enemy is not EnemyAI enemy) return;
if (!this.EnemyControllers.TryGetValue(enemy.GetType(), out IController controller)) return;
controller.OnSecondarySkillHold(enemy);
}
void ReleaseSecondarySkill() {
if (this.Possession.Enemy is not EnemyAI enemy) return;
if (!this.EnemyControllers.TryGetValue(enemy.GetType(), out IController controller)) return;
controller.ReleaseSecondarySkill(enemy);
}
}
@winstxnhdw the bug should be fixed now, HaxCamera is now a core module.
Does it not work if we just let camera stick around? Or must it be destroyed?
Does it not work if we just let camera stick around? Or must it be destroyed?
we can leave the camera, but since is a temporary object, we dont need it, that's why we destroy it, even in ControlCompany they destroy their ghost object.
I think it’s fine to leave the camera then. It’ll make things more reliable.
if (!controller.IsAbleToMove(enemy)) {
return;
}
this.UpdateEnemyPosition(enemy);
controller.OnMovement(enemy, this.CharacterMovement.IsMoving, this.CharacterMovement.IsSprinting);
if (controller.IsAbleToMove(enemy)) {
this.UpdateEnemyPosition(enemy);
controller.OnMovement(enemy, this.CharacterMovement.IsMoving, this.CharacterMovement.IsSprinting);
}
using GameNetcodeStuff;
using Hax;
using UnityEngine;
enum CoilHeadState {
Idle = 0,
Chase = 1
}
internal class CoilHeadController : IEnemyController<SpringManAI> {
bool GetStoppingMovement(SpringManAI enemy) => enemy.Reflect().GetInternalField<bool>("stoppingMovement");
float GetTimeSinceHittingPlayer(SpringManAI enemy) =>
enemy.Reflect().GetInternalField<float>("timeSinceHittingPlayer");
void SetTimeSinceHittingPlayer(SpringManAI enemy, float value) =>
enemy.Reflect().SetInternalField("timeSinceHittingPlayer", value);
public void OnSecondarySkillHold(SpringManAI enemy) => enemy.SetAnimationGoServerRpc();
public void ReleaseSecondarySkill(SpringManAI enemy) => enemy.SetAnimationStopServerRpc();
public bool IsAbleToMove(SpringManAI enemy) => !this.GetStoppingMovement(enemy) || enemy.IsBehaviourState(CoilHeadState.Idle);
public bool IsAbleToRotate(SpringManAI enemy) => !this.GetStoppingMovement(enemy) || enemy.IsBehaviourState(CoilHeadState.Idle);
public float InteractRange(SpringManAI _) => 1.5f;
public void OnOutsideStatusChange(SpringManAI enemy) => enemy.StopSearch(enemy.searchForPlayers, true);
public void OnCollideWithPlayer(SpringManAI enemy, PlayerControllerB player) {
if (enemy.isOutside) {
if(this.GetStoppingMovement(enemy)) return;
if(!enemy.IsBehaviourState(CoilHeadState.Chase)) return;
if(this.GetTimeSinceHittingPlayer(enemy) >= 0f) return;
{
this.SetTimeSinceHittingPlayer(enemy, 0.2f);
player.DamagePlayer(90, true, true, CauseOfDeath.Mauling, 2, false, default);
player.JumpToFearLevel(1f, true);
}
}
}
}
@winstxnhdw im unsure how to fix the noclip while possessing a enemy, it does not follow the camera rotation while moving.
Did you remove MousePan
by accident?
Did you remove
MousePan
by accident?
from where?
From PhantomMod
From
PhantomMod
i dont recall
@winstxnhdw im unsure how to fix the noclip while possessing a enemy, it does not follow the camera rotation while moving.
That was fixed by bringing back the old enemies rotation only for the no clip, recently I made it where the enemy can only accept horizontal rotation from the camera to fix the issue that made it where you can't move forward or backwards when looking up or down, but this also added the bonus effect causing this issue with no clip, so I just brought back the old code for no clip only.
void UpdateEnemyRotation() {
if (this.CharacterMovement is not CharacterMovement characterMovement) return;
if (!this.NoClipEnabled) {
Quaternion horizontalRotation = Quaternion.Euler(0f, this.transform.eulerAngles.y, 0f);
characterMovement.transform.rotation = horizontalRotation;
}
else {
characterMovement.transform.rotation = this.transform.rotation;
}
}
Ill rewrite how to regulate these camera offsets later once im back home to improve it
@winstxnhdw so far everything is perfectly finished.
still gotta stop destroying the camera
@winstxnhdw with the newest changes i also rebuilt how the camera's audio mechanism works and it should not sound muffled anymore.
Nice! What are the pending bugs left?
@winstxnhdw I got a pull request on his pull, he plans on pulling it after you pull his, do you see any problematic things in my pull that would prevent you from pulling it into main? https://github.com/xAstroBoy/lc-hax/pull/4
@winstxnhdw all good, now possessed enemies & enemies that are not supposed to be outside can kill / find targets regardless
we don't merge unfinished code. if ghost girl is not working, please remove it and we can use it for a later PR.
we don't merge unfinished code. if ghost girl is not working, please remove it and we can use it for a later PR.
Done
@winstxnhdw is finished
@winstxnhdw for optimization reasons i remade how the PossessionMod works, basically caching the controller and not parsing it every single time, this way is faster, it won't need to parse it multiple times and it allows other mods to access it which @D1GQ did but in a janky way, instead i replaced with a accessible IController field which i check if is null and then ask the controller event itself.
@winstxnhdw with these new changes, on E , you can use the enemy to interact with any door. i also removed the custom InteractRange and made it all fallback to default 's one which is 4.5f, and is plenty as well, i tested with a linecast showing it, i also disabled the interact option by checking if the controller set the range to 0, which the giant and leviatan has.
I'll merge after my exams this week.
An ex-colleague of mine told me to try this out, @coderabbitai
The recent updates bring a comprehensive overhaul to various aspects of the game, focusing on refining character movement, enhancing camera control, and improving mechanics related to possession and phantom modes. These changes aim to elevate gameplay dynamics, provide more immersive camera experiences, and enrich player engagement with the game world for an enhanced gaming adventure.
File Path | Change Summary |
---|---|
.../Components/CharacterMovement.cs |
Added CanMove property; refactored Move method. |
.../Controllers/BrackenController.cs |
Updated access modifiers, added properties and methods, modified UsePrimarySkill , removed InteractRange . |
.../Controllers/JesterController.cs |
Introduced JesterController class. |
.../Controllers/ManticoilController.cs |
Introduced ManticoilController class. |
.../Controllers/SnareFleaController.cs |
Added UnityEngine , updated UseSecondarySkill and camera offset calculation, removed InteractRange . |
.../Patches/HUDPatch.cs |
Modified with new Harmony patches for HUD and camera logic. |
.../Patches/PossessionPatch.cs |
Adjusted possession-related conditions and event handling. |
.../Core/HaxCamera.cs |
Introduced HaxCamera class for custom camera management. |
.../Helpers/Camera.cs |
Updated logic for obtaining current camera. |
.../Modules/PhantomMod.cs |
Added properties and methods for phantom mode management. |
.../Modules/Possession/Patches/HudPatch.cs |
Added Harmony patches for HUD based on possession state. |
.../Modules/Possession/Patches/PlayerIsTargetablePatch.cs |
Modified player targeting logic based on possession. |
"In the realm of code and fantasy,
Where characters leap and flee,
A rabbit hopped with glee,
For changes vast as the sea.
🌟 With tweaks and patches aplenty,
It danced through the binary,
Crafting worlds so tenderly."
🐰💻✨
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?
[!TIP] For best results, initiate chat on the files or code changes.
@winstxnhdw, welcome! I'm here to assist you with code reviews, answer questions, or help with any specific tasks you have in mind related to your code or pull request. If there's anything specific you'd like assistance with, please feel free to let me know!
@coderabbitai My biggest problem with this PR is that it doesn’t follow the codebase’s style. Can you identify all lines that don’t conform to the general codebase style?
[!TIP] For best results, initiate chat on the files or code changes.
@winstxnhdw, to accurately identify lines that don't conform to the general codebase style, could you provide more details on the specific style guidelines or conventions that the PR should adhere to? Examples or references to your project's coding standards would be incredibly helpful.
@coderabbitai I don’t have time to write an entire style guide but if you look at the rest of the codebase, there’s an obvious and distinct style that can be inferred.
[!TIP] For best results, initiate chat on the files or code changes.
Based on the analysis of the provided code snippets from the codebase and comparing them with the PossessionMod
class, here are the identified style inconsistencies:
{
for classes and methods should be placed on a new line, which is followed in the provided code snippet.PossessionMod
snippet, but ensure they are placed at the top of the file and sorted alphabetically.PossessionMod
snippet as no attributes are used.Without specific lines of code from the PossessionMod
class being flagged for style inconsistencies, it appears the provided snippet largely adheres to the inferred style conventions based on the provided codebase examples. If there are specific areas of concern or additional files you'd like reviewed for style consistency, please let me know!
I am infinitesimally close to just closing this PR right now.
@winstxnhdw is just that the possessed enemy cannot if they are outside their place, and the only way is to patch isPlayerTargetable which i did, you just removed it.
I have no idea what you just said.
I have no idea what you just said.
The commit i reverted has 1) Blocks scanning during possession 2) Allows enemies to attack anywhere if they are possessed. 3) Blocks voting for leaving ship early under possession
What do you mean allow enemies to attack anywhere if they are possessed?
What do you mean allow enemies to attack anywhere if they are possessed?
if you bring a enemy that is not supposed to be outside it won't attack anymore.
Then don't add it into the Mods directory.
Then don't add it into the Mods directory.
is in dependency for a reason
It was in Modules
I thought you were only using the camera during phantom, but you've used it to completely replace the main gameplay camera. That's not acceptable. There are people who would still want to play with the original shaders that you are unable to bring over.
I thought you were only using the camera during phantom, but you've used it to completely replace the main gameplay camera. That's not acceptable. There are people who would still want to play with the original shaders that you are unable to bring over.
I bring all the shaders, i copy the original camera information on spawn , and not tamper with the original camera settings im not replacing the main's gameplay's camera , it should stay untouched.
When you inject while in game, you can see that the colours change slightly. The blur is gone. You could've made it a lot easier for yourself if you just switch back and forth from the new camera and the main camera.
When you inject while in game, you can see that the colours change slightly. The blur is gone. You could've made it a lot easier for yourself if you just switch back and forth from the new camera and the main camera.
the blur ? you can read how the haxcamera is spawned and is not supposed to get rid of that blur or replace the camera, maybe is another mod or something else.
Oh, you're right. I am blind.
There's still too many things I want to change. I don't like how DisablePhantom
is exposed. Phantom should turn off on it's own and not couple with the camera. I'll continue again next week or the week after that.
@winstxnhdw just to let you know, im done collabing to your repo trying to follow your strict requirements.
Fix Enemies Nodes not updating Fix spider mesh not following the current position & rotation when not controlling, the spider will use that last position and claim it as it's nest. add LcHaxCamera and make all mods use that one on phantom mode. add isDead()
add OnOutsideStatusChange to reset all enemies's NavMesh's searches to not be broken when AI Nodes update.
@winstxnhdw all done.
Summary by CodeRabbit
New Features
Refactor
Bug Fixes
Chores