2022-11-23 21:02:33 +08:00
|
|
|
|
/*********************************************************************
|
|
|
|
|
* \file Homeowner1.cs
|
|
|
|
|
* \author Ryan Wang Nian Jing
|
|
|
|
|
* \brief The implemented behaviour tree for the homeowner
|
|
|
|
|
* A prototype to prove that behaviour trees can be worked and expanded
|
|
|
|
|
* on in the custom engine for GAM300 Milestone 3 and expanded over
|
|
|
|
|
* GAM350
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* \copyright Copyright (c) 2022 DigiPen Institute of Technology. Reproduction
|
|
|
|
|
or disclosure of this file or its contents without the prior written
|
|
|
|
|
consent of DigiPen Institute of Technology is prohibited.
|
|
|
|
|
*********************************************************************/
|
|
|
|
|
|
|
|
|
|
using SHADE;
|
|
|
|
|
using SHADE_Scripting.AIBehaviour.BehaviourTree;
|
2023-02-02 16:58:40 +08:00
|
|
|
|
using SHADE_Scripting.Audio;
|
2022-11-23 21:02:33 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
//Variables required for the AI to function
|
|
|
|
|
//To be attached to the game object via the inspector
|
|
|
|
|
public partial class Homeowner1 : BehaviourTree
|
|
|
|
|
{
|
|
|
|
|
private BehaviourTreeEvents _events { get; set; }
|
|
|
|
|
public override BehaviourTreeEvents events { get => _events; }
|
|
|
|
|
|
|
|
|
|
//PATROL FIELDS///////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
[Tooltip("The list of waypoints for the AI to cycle around")]
|
2022-11-24 21:26:05 +08:00
|
|
|
|
private GameObject waypointsPool;
|
|
|
|
|
|
|
|
|
|
private List<GameObject> waypoints;
|
2022-11-23 21:02:33 +08:00
|
|
|
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
[Tooltip("The AI will patrol at this speed")]
|
|
|
|
|
private float patrolSpeed;
|
|
|
|
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
[Tooltip("The speed at which the AI will chase the player if sighted")]
|
|
|
|
|
private float chaseSpeed;
|
|
|
|
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
[Tooltip("Turning speed multiplier of the AI. 10 is good")]
|
|
|
|
|
private float turningSpeed;
|
|
|
|
|
|
|
|
|
|
//FIELD OF VISION/////////////////////////////////////////////////////////////
|
|
|
|
|
[SerializeField]
|
|
|
|
|
[Tooltip("How far the AI can see up to")]
|
|
|
|
|
private float sightDistance;
|
|
|
|
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
[Tooltip("How far the eyes are offset from the AI's actual position")]
|
|
|
|
|
private Vector3 eyeOffset;
|
|
|
|
|
|
|
|
|
|
//ATTACKING///////////////////////////////////////////////////////////////////
|
|
|
|
|
[SerializeField]
|
|
|
|
|
[Tooltip("How near the player mut be to the AI for capture")]
|
|
|
|
|
private float distanceToCapture;
|
|
|
|
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
[Tooltip("How long the player should be in the attack range for successful capture")]
|
|
|
|
|
private float captureTime;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//There's definitely a better way to do this
|
|
|
|
|
[SerializeField]
|
|
|
|
|
[Tooltip("TO BE REMOVED IN 350. Interval multiplier between footsteps")]
|
|
|
|
|
private float footstepSFXIntervalMultiplier;
|
|
|
|
|
|
|
|
|
|
private float footstepTimeRemaining;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//AI tree
|
|
|
|
|
public partial class Homeowner1 : BehaviourTree
|
|
|
|
|
{
|
|
|
|
|
//Called at the start
|
|
|
|
|
protected override void Initialise()
|
|
|
|
|
{
|
|
|
|
|
_events = new Homeowner1Events(this);
|
|
|
|
|
events.Initialise();
|
2022-11-24 21:26:05 +08:00
|
|
|
|
|
2022-11-25 16:12:58 +08:00
|
|
|
|
//(25 Nov) DO NOT Initialise the data here
|
|
|
|
|
/*if (waypointsPool)
|
2022-11-24 21:26:05 +08:00
|
|
|
|
{
|
|
|
|
|
waypoints = (List<GameObject>)waypointsPool.GetChildren();
|
|
|
|
|
SetData("waypoints", waypoints);
|
|
|
|
|
}
|
2022-11-25 16:12:58 +08:00
|
|
|
|
SetData("transform", GetComponent<Transform>());
|
|
|
|
|
SetData("rigidBody", GetComponent<RigidBody>());
|
|
|
|
|
SetData("eyeOffset", eyeOffset);
|
|
|
|
|
SetData("sightDistance", sightDistance);
|
|
|
|
|
SetData("patrolSpeed", patrolSpeed);
|
|
|
|
|
SetData("chaseSpeed", chaseSpeed);
|
|
|
|
|
SetData("turningSpeed", turningSpeed);
|
|
|
|
|
SetData("distanceToCapture", distanceToCapture);
|
|
|
|
|
SetData("baseCaptureTime", captureTime);*/
|
2023-02-02 16:58:40 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//These should be somewhere else
|
2023-02-03 19:37:18 +08:00
|
|
|
|
//Debug.Log("TESTING");
|
2023-02-02 16:58:40 +08:00
|
|
|
|
AudioHandler.audioClipHandlers["BGMUnalert"] = Audio.CreateAudioClip("event:/Music/player_undetected");
|
|
|
|
|
AudioHandler.audioClipHandlers["BGMAlert"] = Audio.CreateAudioClip("event:/Music/player_detected");
|
2023-02-03 00:40:22 +08:00
|
|
|
|
AudioHandler.audioClipHandlers["BGMAdaptive"] = Audio.CreateAudioClip("event:/Music/bgm_adaptive");
|
2023-02-02 16:58:40 +08:00
|
|
|
|
|
|
|
|
|
AudioHandler.audioClipHandlers["SFXFootstep"] = Audio.CreateAudioClip("event:/Homeowner/homeowner_footsteps");
|
|
|
|
|
AudioHandler.audioClipHandlers["SFXDetectAh"] = Audio.CreateAudioClip("event:/Homeowner/homeowner_detect_raccoon");
|
|
|
|
|
AudioHandler.audioClipHandlers["SFXDetectSting"] = Audio.CreateAudioClip("event:/Music/stingers/player_detected");
|
2022-11-23 21:02:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Called every tick
|
|
|
|
|
protected override void Tick()
|
|
|
|
|
{
|
2022-11-25 20:16:31 +08:00
|
|
|
|
//Debug.Log("Ticking");
|
2022-11-25 16:12:58 +08:00
|
|
|
|
//Update data
|
|
|
|
|
if (GetData("waypoints") == null)
|
|
|
|
|
{
|
2022-11-25 20:16:31 +08:00
|
|
|
|
if (waypointsPool != GameObject.Null)
|
2022-11-25 16:12:58 +08:00
|
|
|
|
SetData("waypoints", (List<GameObject>)waypointsPool.GetChildren());
|
2022-11-25 20:16:31 +08:00
|
|
|
|
else
|
|
|
|
|
Debug.LogError("No waypoints, no AI");
|
2022-11-25 16:12:58 +08:00
|
|
|
|
}
|
|
|
|
|
if (GetData("transform") == null)
|
|
|
|
|
SetData("transform", GetComponent<Transform>());
|
|
|
|
|
if (GetData("rigidBody") == null)
|
|
|
|
|
SetData("rigidBody", GetComponent<RigidBody>());
|
|
|
|
|
if (GetData("eyeOffset") == null || (Vector3)GetData("eyeOffset") != eyeOffset)
|
|
|
|
|
SetData("eyeOffset", eyeOffset);
|
|
|
|
|
if (GetData("sightDistance") == null || (float)GetData("sightDistance") != sightDistance)
|
|
|
|
|
SetData("sightDistance", sightDistance);
|
|
|
|
|
if (GetData("patrolSpeed") == null || (float)GetData("patrolSpeed") != patrolSpeed)
|
|
|
|
|
SetData("patrolSpeed", patrolSpeed);
|
|
|
|
|
if (GetData("chaseSpeed") == null || (float)GetData("chaseSpeed") != chaseSpeed)
|
|
|
|
|
SetData("chaseSpeed", chaseSpeed);
|
|
|
|
|
if (GetData("turningSpeed") == null || (float)GetData("turningSpeed") != turningSpeed)
|
|
|
|
|
SetData("turningSpeed", turningSpeed);
|
|
|
|
|
if (GetData("distanceToCapture") == null || (float)GetData("distanceToCapture") != distanceToCapture)
|
|
|
|
|
SetData("distanceToCapture", distanceToCapture);
|
|
|
|
|
if (GetData("baseCaptureTime") == null || (float)GetData("baseCaptureTime") != captureTime)
|
|
|
|
|
SetData("baseCaptureTime", captureTime);
|
|
|
|
|
|
2022-11-23 21:02:33 +08:00
|
|
|
|
events.Tick();
|
|
|
|
|
|
2022-11-24 21:26:05 +08:00
|
|
|
|
//Footsteps SFX, move them somewhere else soon
|
2022-11-23 21:02:33 +08:00
|
|
|
|
float velocity = GetComponent<RigidBody>().LinearVelocity.GetMagnitude();
|
|
|
|
|
|
|
|
|
|
footstepTimeRemaining -= velocity * Time.DeltaTimeF;
|
|
|
|
|
if (footstepTimeRemaining < 0.0f)
|
|
|
|
|
{
|
2023-02-03 00:40:22 +08:00
|
|
|
|
//Audio.PlaySFXOnce2D("event:/Homeowner/homeowner_footsteps");
|
|
|
|
|
//AudioHandler.audioClipHandlers["SFXFootstep"].Play();
|
2022-11-23 21:02:33 +08:00
|
|
|
|
footstepTimeRemaining = footstepSFXIntervalMultiplier;
|
|
|
|
|
}
|
2022-11-25 20:16:31 +08:00
|
|
|
|
//Debug.Log("Ticked");
|
2022-11-23 21:02:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Define the behaviour tree here
|
|
|
|
|
//Order of which nodes are created affects order of execution
|
|
|
|
|
//The tree is called from the root every tick
|
|
|
|
|
protected override BehaviourTreeNode CreateTree()
|
|
|
|
|
{
|
2022-11-25 20:16:31 +08:00
|
|
|
|
//Debug.Log("Creating Tree");
|
2022-11-23 21:02:33 +08:00
|
|
|
|
//Start from the root, structure it like this to make it look like a tree
|
|
|
|
|
BehaviourTreeNode root = new BehaviourTreeSelector("Root", new List<BehaviourTreeNode>
|
|
|
|
|
{
|
2022-11-24 21:26:05 +08:00
|
|
|
|
new BehaviourTreeSequence("Alerted", new List<BehaviourTreeNode>
|
2022-11-23 21:02:33 +08:00
|
|
|
|
{
|
2022-11-25 16:12:58 +08:00
|
|
|
|
new LeafSearch("SearchFOV"),
|
2022-11-23 21:02:33 +08:00
|
|
|
|
new BehaviourTreeSequence("CatchPlayer", new List<BehaviourTreeNode>
|
|
|
|
|
{
|
2022-11-25 16:12:58 +08:00
|
|
|
|
new LeafChase("Chasing"),
|
|
|
|
|
new LeafAttack("Attacking")
|
2022-11-23 21:02:33 +08:00
|
|
|
|
})
|
2022-11-24 21:26:05 +08:00
|
|
|
|
}),
|
2022-11-25 16:12:58 +08:00
|
|
|
|
new LeafPatrol("Patrol")
|
2022-11-23 21:02:33 +08:00
|
|
|
|
});
|
2022-11-25 20:16:31 +08:00
|
|
|
|
//Debug.Log("Tree Created");
|
2022-11-23 21:02:33 +08:00
|
|
|
|
return root;
|
|
|
|
|
}
|
|
|
|
|
}
|