Added maid's knife (dropped from maid)
This commit is contained in:
parent
05ea3dc4c3
commit
69b2bc24cf
|
@ -139,9 +139,11 @@ namespace ScarletMansion {
|
|||
public static Dictionary<string, Func<int>> itemRarityTable = new Dictionary<string, Func<int>>(){
|
||||
{ "Deco. crystal", () => PluginConfig.Instance.crystalWeightValue },
|
||||
{ "Shattered deco. crystal", () => PluginConfig.Instance.crystalBrokenWeightValue },
|
||||
{ "Demonic painting", () => 0 }
|
||||
{ "Demonic painting", () => 0 },
|
||||
{ "Maid's knife", () => 0 }
|
||||
};
|
||||
|
||||
|
||||
public static Flashlight flashlight;
|
||||
public static Flashlight flashlightBB;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using Unity.Netcode;
|
||||
using ScarletMansion.GamePatch.Enemies;
|
||||
|
||||
namespace ScarletMansion.GamePatch.Components {
|
||||
public class ScarletDoorLock : DoorLock {
|
||||
|
@ -84,6 +85,8 @@ namespace ScarletMansion.GamePatch.Components {
|
|||
{ typeof(SandSpiderAI), (e) => e.currentBehaviourStateIndex <= 1 },
|
||||
{ typeof(SpringManAI), (e) => e.currentBehaviourStateIndex == 0 },
|
||||
{ typeof(KnightVariant), (e) => e.currentBehaviourStateIndex == 0 },
|
||||
{ typeof(ButlerEnemyAI), (e) => e.currentBehaviourStateIndex <= 1 },
|
||||
{ typeof(MaidVariant), (e) => e.currentBehaviourStateIndex <= 1 }
|
||||
};
|
||||
|
||||
static readonly Dictionary<Type, float> EnemyDoorDamagePerSecond = new Dictionary<Type, float>(){
|
||||
|
@ -100,6 +103,8 @@ namespace ScarletMansion.GamePatch.Components {
|
|||
{ typeof(SandSpiderAI), 25f },
|
||||
{ typeof(SpringManAI), 12.5f },
|
||||
{ typeof(KnightVariant), 12.5f },
|
||||
{ typeof(ButlerEnemyAI), 50f },
|
||||
{ typeof(MaidVariant), 50f }
|
||||
};
|
||||
|
||||
public bool IsInOpenDoorNormallyState(EnemyAI enemy){
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//using System;
|
||||
using System.Collections;
|
||||
using GameNetcodeStuff;
|
||||
using ScarletMansion.GamePatch.Items;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations.Rigging;
|
||||
|
@ -180,6 +181,10 @@ namespace ScarletMansion.GamePatch.Enemies {
|
|||
// Token: 0x04000110 RID: 272
|
||||
public GameObject knifePrefab;
|
||||
|
||||
public GameObject knifeRender;
|
||||
|
||||
public Transform knifeRenderTransform;
|
||||
|
||||
public AudioSource chaseMusicStart;
|
||||
|
||||
// Token: 0x04000111 RID: 273
|
||||
|
@ -256,6 +261,14 @@ namespace ScarletMansion.GamePatch.Enemies {
|
|||
if (!startedButlerDeathAnimation) {
|
||||
startedButlerDeathAnimation = true;
|
||||
this.creatureAnimator.SetTrigger("Dead");
|
||||
|
||||
knifeRender.SetActive(false);
|
||||
|
||||
if (IsServer) {
|
||||
var newKnife = Object.Instantiate(knifePrefab, base.transform.position + Vector3.up * 0.5f, Quaternion.identity, RoundManager.Instance.spawnedScrapContainer);
|
||||
newKnife.GetComponent<NetworkObject>().Spawn();
|
||||
newKnife.GetComponent<ScarletKnife>().LinkKnifeToMaidServerRpc(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -277,7 +290,6 @@ namespace ScarletMansion.GamePatch.Enemies {
|
|||
base.HitEnemy(force, playerWhoHit, playHitSFX, hitID);
|
||||
enemyHP -= force;
|
||||
|
||||
if (hitID == 5) enemyHP -= 100;
|
||||
if (playerWhoHit != null) berserkModeTimer = 8f;
|
||||
|
||||
if (enemyHP <= 0 && IsOwner) {
|
||||
|
@ -530,7 +542,7 @@ namespace ScarletMansion.GamePatch.Enemies {
|
|||
}
|
||||
|
||||
// and it looks like our target is alone, kill
|
||||
if (currentBehaviourStateIndex == 1 && CheckLineOfSightForPlayer(120f, 50, 2) == targetPlayer && playersInVicinity < 2 && timeSpentWaitingForPlayer > 12f) {
|
||||
if (currentBehaviourStateIndex == 1 && CheckLineOfSightForPlayer(120f, 50, 2) == targetPlayer && playersInVicinity < 2 && timeSpentWaitingForPlayer > 20f) {
|
||||
SwitchToBehaviourStateOnLocalClient(2);
|
||||
SwitchOwnershipAndSetToStateServerRpc(2, targetPlayer.actualClientId, -1f);
|
||||
return;
|
||||
|
|
|
@ -16,6 +16,7 @@ using ScarletMansion.GamePatch.Components;
|
|||
using System.Security.Cryptography;
|
||||
using ScarletMansion.GamePatch.Enemies;
|
||||
using UnityEngine.UI;
|
||||
using ScarletMansion.GamePatch.Items;
|
||||
|
||||
namespace ScarletMansion.GamePatch {
|
||||
|
||||
|
@ -108,6 +109,25 @@ namespace ScarletMansion.GamePatch {
|
|||
return true;
|
||||
}
|
||||
|
||||
private static void FixParticleSystemMaterial(ParticleSystemRenderer toFixParticleSystem, ParticleSystemRenderer copyParticleSystem) {
|
||||
Debug.Log(copyParticleSystem.name);
|
||||
toFixParticleSystem.sharedMaterial = copyParticleSystem.sharedMaterial;
|
||||
}
|
||||
|
||||
private static void FixParticleSystemMaterial(ParticleSystem toFixParticleSystem, ParticleSystem copyParticleSystem) {
|
||||
FixParticleSystemMaterial(toFixParticleSystem.GetComponent<ParticleSystemRenderer>(), copyParticleSystem.GetComponent<ParticleSystemRenderer>());
|
||||
}
|
||||
|
||||
private static void FixParticleSystemMaterialAndChildren(ParticleSystem toFixParticleSystem, ParticleSystem copyParticleSystem) {
|
||||
FixParticleSystemMaterial(toFixParticleSystem, copyParticleSystem);
|
||||
|
||||
for(var i = 0; i < toFixParticleSystem.transform.childCount && i < copyParticleSystem.transform.childCount; ++i) {
|
||||
var child0 = toFixParticleSystem.transform.GetChild(i).GetComponent<ParticleSystemRenderer>();
|
||||
var child1 = copyParticleSystem.transform.GetChild(i).GetComponent<ParticleSystemRenderer>();
|
||||
FixParticleSystemMaterial(child0, child1);
|
||||
}
|
||||
}
|
||||
|
||||
public static void FixMapReferences(StartOfRound round){
|
||||
|
||||
try {
|
||||
|
@ -168,18 +188,7 @@ namespace ScarletMansion.GamePatch {
|
|||
|
||||
var butlerPrefab = butlerItem.enemyType.enemyPrefab;
|
||||
var butlerScript = butlerPrefab.GetComponent<ButlerEnemyAI>();
|
||||
var butlerBloodStabParticle = Utility.FindChildRecurvisely(butlerPrefab.transform, "BloodStabParticle");
|
||||
var butlerBloodParticle = Utility.FindChildRecurvisely(butlerPrefab.transform, "BloodParticle");
|
||||
|
||||
if (GameReadNullCheck(butlerBloodStabParticle, "BloodStabParticle", "Messed up errors will probably happen with blood splats") && GameReadNullCheck(butlerBloodParticle, "BloodParticle", "Messed up errors will probably happen with blood splats")){
|
||||
var ps1 = maidScript.stabBloodParticle.GetComponent<ParticleSystemRenderer>();
|
||||
ps1.material = butlerBloodStabParticle.GetComponent<ParticleSystemRenderer>().material;
|
||||
|
||||
var ps2 = ps1.transform.GetChild(0).GetComponent<ParticleSystemRenderer>();
|
||||
ps2.material = butlerBloodParticle.GetComponent<ParticleSystemRenderer>().material;
|
||||
}
|
||||
|
||||
maidScript.knifePrefab = butlerScript.knifePrefab;
|
||||
FixParticleSystemMaterialAndChildren(maidScript.stabBloodParticle, butlerScript.stabBloodParticle);
|
||||
|
||||
LethalLib.Modules.Enemies.RegisterEnemy(type, 0, Levels.LevelTypes.None, maid.terminalNode, maid.terminalKeyword);
|
||||
}
|
||||
|
@ -276,6 +285,24 @@ namespace ScarletMansion.GamePatch {
|
|||
}
|
||||
}
|
||||
|
||||
var knifeItem = round.allItemsList.itemsList.FirstOrDefault(i => i.name.ToLowerInvariant() == "knife");
|
||||
if (GameReadNullCheck(knifeItem, "knife", "Item will have missing image and sound assets")){
|
||||
var scarletKnife = Assets.scrapItems[3].item;
|
||||
QuickItemFix(scarletKnife, knifeItem);
|
||||
|
||||
var scarletPrefab = scarletKnife.spawnPrefab;
|
||||
var scarletScript = scarletPrefab.GetComponent<ScarletKnife>();
|
||||
|
||||
var knifePrefab = knifeItem.spawnPrefab;
|
||||
var knifeScript = knifePrefab.GetComponent<KnifeItem>();
|
||||
|
||||
scarletScript.hitSFX = knifeScript.hitSFX;
|
||||
scarletScript.swingSFX = knifeScript.swingSFX;
|
||||
|
||||
FixParticleSystemMaterialAndChildren(scarletScript.bloodParticle, knifeScript.bloodParticle);
|
||||
FixParticleSystemMaterial(scarletScript.buffedParticleSystem, knifeScript.bloodParticle);
|
||||
}
|
||||
|
||||
if (Assets.flashlight.item == null) {
|
||||
UpdateFlashlight(Assets.flashlight, "proflashlight", 2);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using GameNetcodeStuff;
|
||||
using OdinSerializer;
|
||||
using ScarletMansion.GamePatch.Enemies;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ScarletMansion.GamePatch.Items
|
||||
{
|
||||
public class ScarletKnife : GrabbableObject {
|
||||
|
||||
public AudioSource knifeAudio;
|
||||
|
||||
private List<RaycastHit> objectsHitByKnifeList = new List<RaycastHit>();
|
||||
|
||||
public PlayerControllerB previousPlayerHeldBy;
|
||||
|
||||
private RaycastHit[] objectsHitByKnife;
|
||||
|
||||
public int knifeHitForce;
|
||||
|
||||
public AudioClip[] hitSFX;
|
||||
|
||||
public AudioClip[] swingSFX;
|
||||
|
||||
private int knifeMask = 11012424;
|
||||
|
||||
private float timeAtLastDamageDealt;
|
||||
|
||||
public ParticleSystem bloodParticle;
|
||||
|
||||
[Header("Scarlet")]
|
||||
public MaidVariant parentMaid;
|
||||
public bool buffed;
|
||||
|
||||
[Header("Buff Animations")]
|
||||
public ParticleSystem buffedParticleSystem;
|
||||
public MeshRenderer knifeRenderer;
|
||||
|
||||
public override void EquipItem() {
|
||||
base.EquipItem();
|
||||
playerHeldBy.equippedUsableItemQE = true;
|
||||
parentMaid = null;
|
||||
}
|
||||
|
||||
public override void LateUpdate(){
|
||||
base.LateUpdate();
|
||||
if (parentMaid) {
|
||||
transform.position = parentMaid.knifeRenderTransform.position;
|
||||
transform.rotation = parentMaid.knifeRenderTransform.rotation;
|
||||
}
|
||||
}
|
||||
|
||||
public override void ItemActivate(bool used, bool buttonDown = true) {
|
||||
|
||||
if (playerHeldBy != null) {
|
||||
if (playerHeldBy.activatingItem) return;
|
||||
|
||||
RoundManager.PlayRandomClip(knifeAudio, swingSFX);
|
||||
|
||||
previousPlayerHeldBy = playerHeldBy;
|
||||
if (playerHeldBy.IsOwner) playerHeldBy.playerBodyAnimator.SetTrigger("UseHeldItem1");
|
||||
}
|
||||
|
||||
if (IsOwner) {
|
||||
HitKnife();
|
||||
}
|
||||
}
|
||||
|
||||
public override void ItemInteractLeftRight(bool right) {
|
||||
base.ItemInteractLeftRight(right);
|
||||
if (playerHeldBy != null) {
|
||||
if (!right && !buffed && playerHeldBy.IsOwner && !playerHeldBy.activatingItem && !StartOfRound.Instance.inShipPhase) {
|
||||
BuffShovelServerRpc(playerHeldBy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void HitKnife(bool cancel = false) {
|
||||
if (previousPlayerHeldBy == null) {
|
||||
Debug.LogError("Previousplayerheldby is null on this client when HitShovel is called.");
|
||||
return;
|
||||
}
|
||||
previousPlayerHeldBy.activatingItem = false;
|
||||
bool flag = false;
|
||||
bool flag2 = false;
|
||||
int num = -1;
|
||||
if (!cancel) {
|
||||
previousPlayerHeldBy.twoHanded = false;
|
||||
objectsHitByKnife = Physics.SphereCastAll(previousPlayerHeldBy.gameplayCamera.transform.position + previousPlayerHeldBy.gameplayCamera.transform.right * 0.1f, 0.3f, previousPlayerHeldBy.gameplayCamera.transform.forward, 0.75f, knifeMask, QueryTriggerInteraction.Collide);
|
||||
objectsHitByKnifeList = objectsHitByKnife.OrderBy((RaycastHit x) => x.distance).ToList();
|
||||
for (int i = 0; i < objectsHitByKnifeList.Count; i++) {
|
||||
if (objectsHitByKnifeList[i].transform.gameObject.layer == 8 || objectsHitByKnifeList[i].transform.gameObject.layer == 11) {
|
||||
flag = true;
|
||||
string text = objectsHitByKnifeList[i].collider.gameObject.tag;
|
||||
for (int j = 0; j < StartOfRound.Instance.footstepSurfaces.Length; j++) {
|
||||
if (StartOfRound.Instance.footstepSurfaces[j].surfaceTag == text) {
|
||||
num = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!objectsHitByKnifeList[i].transform.TryGetComponent<IHittable>(out var component)
|
||||
|| objectsHitByKnifeList[i].transform == previousPlayerHeldBy.transform
|
||||
|| (!(objectsHitByKnifeList[i].point == Vector3.zero)
|
||||
&& Physics.Linecast(previousPlayerHeldBy.gameplayCamera.transform.position, objectsHitByKnifeList[i].point, out var _, StartOfRound.Instance.collidersAndRoomMaskAndDefault))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
flag = true;
|
||||
Vector3 forward = previousPlayerHeldBy.gameplayCamera.transform.forward;
|
||||
try {
|
||||
if (Time.realtimeSinceStartup - timeAtLastDamageDealt > 0.43f) {
|
||||
timeAtLastDamageDealt = Time.realtimeSinceStartup;
|
||||
|
||||
// buff
|
||||
if (buffed) {
|
||||
// prevent the player from one-shotting their friends
|
||||
var target = component is PlayerControllerB ? previousPlayerHeldBy as IHittable : component;
|
||||
target.Hit(50, forward, previousPlayerHeldBy, playHitSFX: true);
|
||||
UnBuffShovelServerRpc();
|
||||
}
|
||||
// normal knife
|
||||
else {
|
||||
component.Hit(knifeHitForce, forward, previousPlayerHeldBy, playHitSFX: true);
|
||||
}
|
||||
|
||||
bloodParticle.Play(withChildren: true);
|
||||
}
|
||||
flag2 = true;
|
||||
}
|
||||
catch (Exception arg) {
|
||||
Debug.Log($"Exception caught when hitting object with shovel from player #{previousPlayerHeldBy.playerClientId}: {arg}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
RoundManager.PlayRandomClip(knifeAudio, hitSFX);
|
||||
UnityEngine.Object.FindObjectOfType<RoundManager>().PlayAudibleNoise(base.transform.position, 17f, 0.8f);
|
||||
if (!flag2 && num != -1) {
|
||||
knifeAudio.PlayOneShot(StartOfRound.Instance.footstepSurfaces[num].hitSurfaceSFX);
|
||||
WalkieTalkie.TransmitOneShotAudio(knifeAudio, StartOfRound.Instance.footstepSurfaces[num].hitSurfaceSFX);
|
||||
}
|
||||
|
||||
HitShovelServerRpc(num);
|
||||
}
|
||||
}
|
||||
|
||||
[ServerRpc]
|
||||
public void HitShovelServerRpc(int hitSurfaceID) {
|
||||
HitShovelClientRpc(hitSurfaceID);
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void HitShovelClientRpc(int hitSurfaceID) {
|
||||
if(!base.IsOwner) {
|
||||
RoundManager.PlayRandomClip(knifeAudio, hitSFX);
|
||||
if (hitSurfaceID != -1) HitSurfaceWithKnife(hitSurfaceID);
|
||||
}
|
||||
}
|
||||
|
||||
private void HitSurfaceWithKnife(int hitSurfaceID) {
|
||||
knifeAudio.PlayOneShot(StartOfRound.Instance.footstepSurfaces[hitSurfaceID].hitSurfaceSFX);
|
||||
WalkieTalkie.TransmitOneShotAudio(knifeAudio, StartOfRound.Instance.footstepSurfaces[hitSurfaceID].hitSurfaceSFX);
|
||||
}
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void BuffShovelServerRpc(NetworkBehaviourReference playerReference){
|
||||
BuffShovelClientRpc(playerReference);
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void BuffShovelClientRpc(NetworkBehaviourReference playerReference){
|
||||
if (playerReference.TryGet<PlayerControllerB>(out var player)){
|
||||
StartCoroutine(BuffCoroutine(player));
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator BuffCoroutine(PlayerControllerB player){
|
||||
player.playerBodyAnimator.SetTrigger("UseHeldItem1");
|
||||
player.activatingItem = true;
|
||||
yield return new WaitForSeconds(0.25f);
|
||||
|
||||
player.DamagePlayer(PluginConfig.Instance.maidKnifeSelfDamageValue, true, true, CauseOfDeath.Stabbing);
|
||||
bloodParticle.Play(withChildren: true);
|
||||
RoundManager.PlayRandomClip(knifeAudio, hitSFX);
|
||||
|
||||
buffed = true;
|
||||
buffedParticleSystem.Play();
|
||||
knifeRenderer.material.color = Color.red;
|
||||
|
||||
player.activatingItem = false;
|
||||
}
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void UnBuffShovelServerRpc(){
|
||||
UnBuffShovelClientRpc();
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void UnBuffShovelClientRpc(){
|
||||
buffed = false;
|
||||
buffedParticleSystem.Stop();
|
||||
knifeRenderer.material.color = Color.white;
|
||||
}
|
||||
|
||||
[ServerRpc]
|
||||
public void LinkKnifeToMaidServerRpc(NetworkBehaviourReference maidReference){
|
||||
LinkKnifeToMaidClientRpc(maidReference);
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void LinkKnifeToMaidClientRpc(NetworkBehaviourReference maidReference) {
|
||||
if (maidReference.TryGet<MaidVariant>(out var maid)){
|
||||
parentMaid = maid;
|
||||
} else {
|
||||
Debug.LogWarning($"Could not get parent maid for scarlet maid. Spooky I guess");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ namespace ScarletMansion {
|
|||
public class Plugin : BaseUnityPlugin {
|
||||
public const string modGUID = "ImoutoSama.ScarletMansion";
|
||||
private const string modName = "Scarlet Mansion";
|
||||
private const string modVersion = "1.3.17";
|
||||
private const string modVersion = "1.3.18";
|
||||
|
||||
public readonly Harmony harmony = new Harmony(modGUID);
|
||||
|
||||
|
|
|
@ -244,6 +244,21 @@ namespace ScarletMansion {
|
|||
new AcceptableValueRange<int>(0, 999)
|
||||
);
|
||||
|
||||
public static ConfigEntryBundle<int> maidKnifeSelfDamage = new ConfigEntryBundle<int>(
|
||||
dungeonLootPrefix,
|
||||
"Maid Knife Feed Damage",
|
||||
50,
|
||||
"The amount of self damage taken by feeding the maid's knife. Can kill.",
|
||||
null,
|
||||
new AcceptableValueRange<int>(0, 100)
|
||||
);
|
||||
|
||||
public float lootMultiplierValue;
|
||||
public int crystalWeightValue;
|
||||
public int crystalBrokenWeightValue;
|
||||
public int maidKnifeSelfDamageValue;
|
||||
|
||||
// enemies
|
||||
public static ConfigEntryBundle<float> mapHazardsMultiplier = new ConfigEntryBundle<float>(
|
||||
dungeonEnemiesPrefix,
|
||||
"Map Hazards Multiplier",
|
||||
|
@ -298,10 +313,6 @@ namespace ScarletMansion {
|
|||
new AcceptableValueRange<int>(0, 999)
|
||||
);
|
||||
|
||||
public float lootMultiplierValue;
|
||||
public int crystalWeightValue;
|
||||
public int crystalBrokenWeightValue;
|
||||
|
||||
public float mapHazardsMultiplierValue;
|
||||
|
||||
public int minIndoorEnemySpawnCountValue;
|
||||
|
|
|
@ -205,6 +205,7 @@
|
|||
<Compile Include="GamePatch\Items\FlandreCrystal.cs" />
|
||||
<Compile Include="GamePatch\Items\IScarletItem.cs" />
|
||||
<Compile Include="GamePatch\Items\ScarletFlashlight.cs" />
|
||||
<Compile Include="GamePatch\Items\ScarletKnife.cs" />
|
||||
<Compile Include="GamePatch\Items\ScarletPainting.cs" />
|
||||
<Compile Include="GamePatch\JesterAIPatch.cs" />
|
||||
<Compile Include="GamePatch\LoadAssetsIntoLevelPatch.cs" />
|
||||
|
|
Loading…
Reference in New Issue