LadyAliceMargatroid fd731baf2f Added configs for items and enemies
Critical damage renamed to marked for death and all share the same mechanic now
Revelant now slows down to speed over a fixed short amount instead the nonworking jank before
Moved item/enemy injection to DunGenPlus
2024-12-15 09:23:53 -08:00

466 lines
15 KiB
C#

using GameNetcodeStuff;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
namespace ScarletMansion.GamePatch.Enemies {
public class KnightV2Variant : EnemyAI {
public AISearchRoutine searchForPlayers;
private float checkLineOfSightInterval;
private bool hasEnteredChaseMode;
private bool stoppingMovement;
private bool hasStopped;
public AnimationStopPoints animStopPoints;
private float currentChaseSpeed = 13f;
private float currentAnimSpeed = 1f;
private PlayerControllerB previousTarget;
private bool wasOwnerLastFrame;
private float stopAndGoMinimumInterval;
private float hitPlayerTimer;
public AudioClip[] springNoises;
public AudioClip enterCooldownSFX;
public Collider mainCollider;
private float loseAggroTimer;
private float timeSinceHittingPlayer;
private bool movingOnOffMeshLink;
private Coroutine offMeshLinkCoroutine;
private float stopMovementTimer;
public float timeSpentMoving;
public float onCooldownPhase;
private bool setOnCooldown;
public float timeAtLastCooldown;
private Vector3 previousPosition;
private float checkPositionInterval;
private bool isMakingDistance;
// Token: 0x04000F2A RID: 3882
private bool inCooldownAnimation;
public override void Start(){
base.Start();
currentChaseSpeed = PluginConfig.Instance.knightEnemyValue.speed;
if (IsOwner && KnightSpawnManager.Instance) {
var index = KnightSpawnManager.Instance.GetSpawnPointIndex();
if (index == -1) return;
SyncKnightReplacementClientRpc(index);
}
}
[ServerRpc(RequireOwnership = false)]
public void SetCoilheadOnCooldownServerRpc(float cooldown) {
SetCoilheadOnCooldownClientRpc(cooldown);
}
// Token: 0x06000F6F RID: 3951 RVA: 0x000942FC File Offset: 0x000924FC
[ClientRpc]
public void SetCoilheadOnCooldownClientRpc(float cooldown) {
timeSpentMoving = 0f;
if (cooldown > 0f) {
onCooldownPhase = cooldown;
setOnCooldown = true;
inCooldownAnimation = true;
SwitchToBehaviourStateOnLocalClient(0);
creatureVoice.PlayOneShot(enterCooldownSFX);
if (animStopPoints.animationPosition == 1) creatureAnimator.SetTrigger("springBoing");
else creatureAnimator.SetTrigger("springBoingPosition2");
creatureAnimator.SetFloat("walkSpeed", 0f);
return;
}
onCooldownPhase = 0f;
setOnCooldown = false;
timeAtLastCooldown = Time.realtimeSinceStartup;
}
// Token: 0x06000F70 RID: 3952 RVA: 0x0009443C File Offset: 0x0009263C
public override void DoAIInterval() {
base.DoAIInterval();
if (StartOfRound.Instance.allPlayersDead) return;
if (isEnemyDead) return;
var currentBehaviourStateIndex = this.currentBehaviourStateIndex;
if (currentBehaviourStateIndex != 0) {
if (currentBehaviourStateIndex != 1) return;
if (searchForPlayers.inProgress) StopSearch(searchForPlayers, true);
if (TargetClosestPlayer(1.5f, false, 70f)) {
if (previousTarget != targetPlayer) {
previousTarget = targetPlayer;
ChangeOwnershipOfEnemy(targetPlayer.actualClientId);
}
if (Time.realtimeSinceStartup - timeSinceHittingPlayer > 7f && !stoppingMovement) {
if (Vector3.Distance(targetPlayer.transform.position, transform.position) <= 40f || CheckLineOfSightForPosition(targetPlayer.gameplayCamera.transform.position, 180f, 140, -1f, null)) {
loseAggroTimer = 0f;
return;
}
loseAggroTimer += AIIntervalTime;
if (loseAggroTimer > 4.5f) {
SwitchToBehaviourState(0);
ChangeOwnershipOfEnemy(StartOfRound.Instance.allPlayerScripts[0].actualClientId);
return;
}
}
} else {
var flag = false;
for (var i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++) {
if (StartOfRound.Instance.allPlayerScripts[i].HasLineOfSightToPosition(transform.position + Vector3.up * 0.3f, 68f, 60, -1f) || StartOfRound.Instance.allPlayerScripts[i].HasLineOfSightToPosition(transform.position + Vector3.up * 1.6f, 68f, 60, -1f)) {
flag = true;
break;
}
}
if (!flag) {
loseAggroTimer += AIIntervalTime;
if (loseAggroTimer > 1f) {
SwitchToBehaviourState(0);
ChangeOwnershipOfEnemy(StartOfRound.Instance.allPlayerScripts[0].actualClientId);
}
}
}
} else {
if (!IsServer) {
ChangeOwnershipOfEnemy(StartOfRound.Instance.allPlayerScripts[0].actualClientId);
return;
}
if (onCooldownPhase > 0f) {
agent.speed = 0f;
SetDestinationToPosition(transform.position, false);
onCooldownPhase -= AIIntervalTime;
return;
}
if (setOnCooldown) {
setOnCooldown = false;
SetCoilheadOnCooldownClientRpc(0f);
}
loseAggroTimer = 0f;
for (var j = 0; j < StartOfRound.Instance.allPlayerScripts.Length; j++) {
if (PlayerIsTargetable(StartOfRound.Instance.allPlayerScripts[j], false, false)) {
if (StartOfRound.Instance.allPlayerScripts[j].HasLineOfSightToPosition(transform.position + Vector3.up * 0.3f, 60f, 20, -1f)) {
targetPlayer = StartOfRound.Instance.allPlayerScripts[j];
SwitchToBehaviourState(1);
}
if (!PathIsIntersectedByLineOfSight(StartOfRound.Instance.allPlayerScripts[j].transform.position, false, false, false) && !Physics.Linecast(transform.position + Vector3.up * 0.5f, StartOfRound.Instance.allPlayerScripts[j].gameplayCamera.transform.position, StartOfRound.Instance.collidersAndRoomMaskAndDefault) && Vector3.Distance(transform.position, StartOfRound.Instance.allPlayerScripts[j].transform.position) < 30f) {
SwitchToBehaviourState(1);
return;
}
}
}
agent.speed = 6f;
if (!searchForPlayers.inProgress) {
movingTowardsTargetPlayer = false;
SetDestinationToPosition(transform.position, false);
StartSearch(transform.position, searchForPlayers);
return;
}
}
}
// Token: 0x06000F71 RID: 3953 RVA: 0x00094882 File Offset: 0x00092A82
private IEnumerator Parabola(NavMeshAgent agent, float height, float duration) {
var data = agent.currentOffMeshLinkData;
var startPos = agent.transform.position;
var endPos = data.endPos + Vector3.up * agent.baseOffset;
var normalizedTime = 0f;
while (normalizedTime < 1f && data.valid && data.activated && IsOwner) {
var num = height * 4f * (normalizedTime - normalizedTime * normalizedTime);
agent.transform.position = Vector3.Lerp(startPos, endPos, normalizedTime) + num * Vector3.up;
normalizedTime += Time.deltaTime / duration;
yield return null;
}
agent.CompleteOffMeshLink();
offMeshLinkCoroutine = null;
yield break;
}
// Token: 0x06000F72 RID: 3954 RVA: 0x000948A8 File Offset: 0x00092AA8
private void StopOffMeshLinkMovement() {
if (offMeshLinkCoroutine != null) {
StopCoroutine(offMeshLinkCoroutine);
offMeshLinkCoroutine = null;
var currentOffMeshLinkData = agent.currentOffMeshLinkData;
agent.CompleteOffMeshLink();
if (currentOffMeshLinkData.valid) {
if (Vector3.SqrMagnitude(transform.position - currentOffMeshLinkData.startPos) < Vector3.SqrMagnitude(transform.position - currentOffMeshLinkData.endPos)) {
agent.Warp(currentOffMeshLinkData.startPos);
return;
}
agent.Warp(currentOffMeshLinkData.endPos);
return;
}
}
}
// Token: 0x06000F73 RID: 3955 RVA: 0x000949B0 File Offset: 0x00092BB0
private void DoSpringAnimation(bool springPopUp = false) {
if (GameNetworkManager.Instance.localPlayerController.HasLineOfSightToPosition(transform.position, 70f, 25, -1f)) {
var num = Vector3.Distance(transform.position, GameNetworkManager.Instance.localPlayerController.transform.position);
if (num < 4f) {
GameNetworkManager.Instance.localPlayerController.JumpToFearLevel(0.9f, true);
} else if (num < 9f) {
GameNetworkManager.Instance.localPlayerController.JumpToFearLevel(0.4f, true);
}
}
if (currentAnimSpeed > 2f || springPopUp) {
RoundManager.PlayRandomClip(creatureVoice, springNoises, false, 1f, 0, 1000);
if (animStopPoints.animationPosition == 1) creatureAnimator.SetTrigger("springBoing");
else creatureAnimator.SetTrigger("springBoingPosition2");
}
}
// Token: 0x06000F74 RID: 3956 RVA: 0x00094AA4 File Offset: 0x00092CA4
public override void Update() {
base.Update();
if (isEnemyDead) return;
if (hitPlayerTimer >= 0f) hitPlayerTimer -= Time.deltaTime;
if (!IsOwner) {
stopMovementTimer = 5f;
loseAggroTimer = 0f;
if (offMeshLinkCoroutine != null) StopCoroutine(offMeshLinkCoroutine);
}
if (IsOwner) {
if (agent.isOnOffMeshLink) {
if (!stoppingMovement && agent.currentOffMeshLinkData.activated) {
if (offMeshLinkCoroutine == null) offMeshLinkCoroutine = StartCoroutine(Parabola(agent, 0.6f, 0.5f));
}
else {
StopOffMeshLinkMovement();
}
} else if (offMeshLinkCoroutine != null) {
StopOffMeshLinkMovement();
}
}
creatureAnimator.SetBool("OnCooldown", setOnCooldown);
if (setOnCooldown) {
mainCollider.isTrigger = true;
stoppingMovement = true;
hasStopped = true;
return;
}
var currentBehaviourStateIndex = this.currentBehaviourStateIndex;
if (currentBehaviourStateIndex == 0) {
agent.autoTraverseOffMeshLink = false;
creatureAnimator.SetFloat("walkSpeed", 2.5f);
stoppingMovement = false;
hasStopped = false;
return;
}
if (currentBehaviourStateIndex != 1) return;
if (IsOwner) {
if (onCooldownPhase > 0f) {
SwitchToBehaviourState(0);
return;
}
if (stopAndGoMinimumInterval > 0f) stopAndGoMinimumInterval -= Time.deltaTime;
if (!wasOwnerLastFrame) {
wasOwnerLastFrame = true;
if (!stoppingMovement && hitPlayerTimer < 0.12f) agent.speed = currentChaseSpeed;
else agent.speed = 0f;
}
var flag = false;
for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++) {
if (PlayerIsTargetable(StartOfRound.Instance.allPlayerScripts[i], false, false) && (StartOfRound.Instance.allPlayerScripts[i].HasLineOfSightToPosition(transform.position + Vector3.up * 0.25f, 68f, 60, -1f) || StartOfRound.Instance.allPlayerScripts[i].HasLineOfSightToPosition(transform.position + Vector3.up * 1.6f, 68f, 60, -1f)) && Vector3.Distance(StartOfRound.Instance.allPlayerScripts[i].gameplayCamera.transform.position, eye.position) > 0.3f) {
flag = true;
}
}
if (stunNormalizedTimer > 0f) flag = true;
if (flag != stoppingMovement && stopAndGoMinimumInterval <= 0f) {
stopAndGoMinimumInterval = 0.15f;
if (flag) SetAnimationStopServerRpc();
else SetAnimationGoServerRpc();
stoppingMovement = flag;
}
}
var num = 0f;
if (stoppingMovement) {
if (animStopPoints.canAnimationStop || stopMovementTimer > 0.27f) {
if (!hasStopped) {
hasStopped = true;
DoSpringAnimation(false);
} else if (inCooldownAnimation) {
inCooldownAnimation = false;
DoSpringAnimation(true);
}
if (RoundManager.Instance.currentMineshaftElevator != null && Vector3.Distance(transform.position, RoundManager.Instance.currentMineshaftElevator.elevatorInsidePoint.position) < 1f) {
num = 0.5f;
}
if (mainCollider.isTrigger && Vector3.Distance(GameNetworkManager.Instance.localPlayerController.transform.position, transform.position) > 0.3f) {
mainCollider.isTrigger = false;
}
creatureAnimator.SetFloat("walkSpeed", 0f);
currentAnimSpeed = 0f;
if (IsOwner) {
agent.speed = 0f;
movingTowardsTargetPlayer = false;
SetDestinationToPosition(transform.position, false);
}
} else {
stopMovementTimer += Time.deltaTime;
}
} else {
stopMovementTimer = 0f;
if (hasStopped) {
hasStopped = false;
mainCollider.isTrigger = true;
isMakingDistance = true;
}
currentAnimSpeed = Mathf.Lerp(currentAnimSpeed, currentChaseSpeed * 0.4597f, 5f * Time.deltaTime);
creatureAnimator.SetFloat("walkSpeed", currentAnimSpeed);
inCooldownAnimation = false;
if (IsServer) {
if (checkPositionInterval <= 0f) {
checkPositionInterval = 0.65f;
isMakingDistance = (Vector3.Distance(transform.position, previousPosition) > 0.5f);
previousPosition = transform.position;
} else {
checkPositionInterval -= Time.deltaTime;
}
if (isMakingDistance) {
num = 1f;
} else {
num = 0.2f;
}
}
if (IsOwner) {
agent.speed = Mathf.Lerp(agent.speed, currentChaseSpeed, 4.5f * Time.deltaTime);
movingTowardsTargetPlayer = true;
}
}
if (IsServer) {
if (num > 0f) {
timeSpentMoving += Time.deltaTime * num;
}
if (timeSpentMoving > 9f) {
onCooldownPhase = 11f;
setOnCooldown = true;
inCooldownAnimation = true;
SetCoilheadOnCooldownClientRpc(25f);
SwitchToBehaviourStateOnLocalClient(0);
}
}
}
// Token: 0x06000F75 RID: 3957 RVA: 0x00094F98 File Offset: 0x00093198
[ServerRpc]
public void SetAnimationStopServerRpc() {
SetAnimationStopClientRpc();
}
// Token: 0x06000F76 RID: 3958 RVA: 0x000950AC File Offset: 0x000932AC
[ClientRpc]
public void SetAnimationStopClientRpc() {
stoppingMovement = true;
}
// Token: 0x06000F77 RID: 3959 RVA: 0x0009517C File Offset: 0x0009337C
[ServerRpc]
public void SetAnimationGoServerRpc() {
SetAnimationGoClientRpc();
}
// Token: 0x06000F78 RID: 3960 RVA: 0x00095290 File Offset: 0x00093490
[ClientRpc]
public void SetAnimationGoClientRpc() {
stoppingMovement = false;
}
// Token: 0x06000F79 RID: 3961 RVA: 0x00095360 File Offset: 0x00093560
public override void OnCollideWithPlayer(Collider other) {
base.OnCollideWithPlayer(other);
if (stoppingMovement || currentBehaviourStateIndex != 1 || hitPlayerTimer >= 0f || setOnCooldown || (Time.realtimeSinceStartup - timeAtLastCooldown) < 0.45f) {
return;
}
var playerControllerB = MeetsStandardPlayerCollisionConditions(other, false, false);
if (playerControllerB != null) {
hitPlayerTimer = 0.2f;
playerControllerB.DamagePlayer(90, true, true, CauseOfDeath.Mauling, 0);
playerControllerB.JumpToFearLevel(1f, true);
timeSinceHittingPlayer = Time.realtimeSinceStartup;
if (playerControllerB.isPlayerDead) {
Assets.onPlayerDeath.Call(new ModPatch.CoronerParameters(playerControllerB, ModPatch.CoronerDeathEnum.Knight));
}
SetCoilheadOnCooldownServerRpc(5f);
}
}
[ClientRpc]
public void SyncKnightReplacementClientRpc(int index){
SyncKnightReplacement(index);
}
public void SyncKnightReplacement(int index){
Plugin.logger.LogDebug($"Spawning knight at {index}");
try {
var target = KnightSpawnManager.Instance.GetSpawnPointTransform(index);
target.gameObject.SetActive(false);
transform.position = target.position;
transform.rotation = target.rotation;
serverPosition = target.position;
if (agent == null) agent = GetComponentInChildren<NavMeshAgent>();
agent.Warp(target.position);
if (IsOwner) {
SyncPositionToClients();
}
} catch (Exception e){
Plugin.logger.LogError($"Tried to knight spawn at {index}, but completely failed");
Plugin.logger.LogError(e);
}
}
}
}