2023-01-04 21:23:02 +01:00
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
using System.Threading.Tasks ;
using UnityEngine ;
[RequireComponent(typeof(NPC))]
[RequireComponent(typeof(Enemy))]
public class ThugNPCFollowing : MonoBehaviour
{
public const string ACTION_KEY = "ATTACKING" ;
private Rigidbody2D myRigidbody ;
public Animator anim ;
private Vector2 movement ;
public bool shouldRotate ;
public Vector3 dir ;
[Header("Following Logic")]
public Vector3 homePosition ;
public Transform targetPosition ;
public AStarPathfindingAgent agent ;
public bool isDuringFollowing = false ; // var is setted by trigger range
//public GameObject player;
[Header("Core Logic")]
public bool approaching = false ;
public bool isAfterAction = false ;
public float chasingRadius = 6f ; // radious where Npc start attacking ! ! !
[Header("Attacking Logic")] // TRASH - dupplicated from Following Enemy - move params to Enemy
public float attackingRadius = 1.5f ; // radious where Npc start attacking ! ! !
public bool hit = false ;
public bool firstAttack = false ;
public float timerDmg = 0f ;
public float waitTime = 1.0f ;
public float timerHit = 0f ;
public float hitWaitTime = 0.55f ;
public float expValue ;
public float thrust ;
public float knockTime ;
//public int isKilled; - movet do Enemy
//isKilled = 0 - mob ALIVE
//isKilled = 1 - mob DEAD
public int isKilled2 ;
public bool isPanelEnabled = true ;
void Awake ( )
{
agent = GetComponent < AStarPathfindingAgent > ( ) ;
homePosition = new Vector3 ( gameObject . transform . position . x , gameObject . transform . position . y , gameObject . transform . position . z ) ;
}
// Start is called before the first frame update
void Start ( )
{
targetPosition = GameObject . FindWithTag ( "Player" ) . transform ;
//Copy from Eollwoing
if ( OnMapAppearanceMethod . IsNewGame ( ) )
{
gameObject . GetComponent < Enemy > ( ) . isKilled = 0 ;
}
if ( gameObject . GetComponent < Enemy > ( ) . health < = 0 )
gameObject . GetComponent < Enemy > ( ) . isKilled = 1 ;
else // Else read saved value
gameObject . GetComponent < Enemy > ( ) . isKilled = PlayerPrefs . GetInt ( gameObject . GetComponent < Enemy > ( ) . enemyName + "-S" ) ;
if ( gameObject . GetComponent < Enemy > ( ) . isKilled = = 1 )
{
gameObject . SetActive ( false ) ;
gameObject . GetComponent < Enemy > ( ) . isKilled = 0 ;
}
myRigidbody = GetComponent < Rigidbody2D > ( ) ;
anim = GetComponent < Animator > ( ) ;
}
// Update is called once per frame
public void Update ( )
{
// 0 Cofigure Animator
if ( Vector2 . Distance ( targetPosition . position , transform . position ) < = chasingRadius )
{
Debug . Log ( "Chase" ) ;
dir = targetPosition . position - transform . position ;
float angle = Mathf . Atan2 ( dir . y , dir . x ) * Mathf . Rad2Deg ;
dir . Normalize ( ) ;
movement = dir ;
anim . SetBool ( "isRunning" , movement ! = Vector2 . zero ) ;
Debug . Log ( shouldRotate ) ;
if ( shouldRotate )
{
anim . SetFloat ( "Xinfo" , dir . x ) ;
anim . SetFloat ( "Yinfo" , dir . y ) ;
}
}
// 1. Check range and decide which action do
// Following player detection
if ( IsInChassingRadious ( ) )
{
// 2'nd state alow us to brak going to hom,e action to follow player again
if ( gameObject . GetComponent < NPC > ( ) . State = = NPCStateEnum . Pending | | gameObject . GetComponent < NPC > ( ) . State = = NPCStateEnum . Walking )
{
approaching = true ;
gameObject . GetComponent < NPC > ( ) . State = NPCStateEnum . Walking ;
}
} else
{
// Turn around and go to home position
if ( approaching )
{
approaching = false ;
2023-01-05 13:24:58 +01:00
anim . SetBool ( "isRunning" , true ) ;
2023-01-04 21:23:02 +01:00
gameObject . GetComponent < NPC > ( ) . State = NPCStateEnum . Walking ;
}
}
// 2.Take action based on conditions around
HandleState ( ) ;
// 3.
// COPIED FROM Following Enemy scripts
// Taking hit logic
timerHit + = Time . deltaTime ;
if ( hit = = true )
{
if ( timerHit > = hitWaitTime )
{
TakeDamage ( PlayerPrefs . GetFloat ( "attackValue" ) ) ;
hit = false ;
timerHit = 0f ;
TakeKnockback ( ) ;
}
}
// Detecting "is alive" logic
if ( gameObject . active = = false )
{
gameObject . GetComponent < Enemy > ( ) . isKilled = 1 ;
PlayerPrefs . SetInt ( gameObject . GetComponent < Enemy > ( ) . enemyName , gameObject . GetComponent < Enemy > ( ) . isKilled ) ;
}
}
public void CheckDistance ( )
{
StopAllCoroutines ( ) ;
// isDuringFollowing - avr is setted by trigger range
if ( approaching & & ! IsInActionRadious ( ) )
{
agent . FindPath ( ) ;
StartCoroutine ( agent . FollowPath ( ) ) ;
}
else if ( approaching )
{
// in this script we set attacking mode
SetActionAfterMetConditions ( ) ;
agent . path . Clear ( ) ; // if we are able to talgk we dont want go go further player
}
else if ( ! approaching )
{
if ( Vector2 . Distance ( transform . position , homePosition ) > 0.8f ) // cont vale - path finding stop moving them before reachin position well..
{
agent . point = homePosition ;
agent . FindPoint ( ) ;
StartCoroutine ( agent . FollowPath ( ) ) ;
}
else
{
2023-01-05 13:24:58 +01:00
anim . SetBool ( "isRunning" , false ) ;
2023-01-04 21:23:02 +01:00
gameObject . GetComponent < NPC > ( ) . State = NPCStateEnum . Pending ;
2023-01-05 13:24:58 +01:00
2023-01-04 21:23:02 +01:00
}
}
}
#region Taking damage from Player detection
public void OnTriggerEnter2D ( Collider2D collision )
{
// Hit logic
if ( collision . gameObject . tag = = "AttackHitbox" | | collision . gameObject . tag = = "PickaxeHitbox" )
{
hit = true ;
}
}
public void OnTriggerExit2D ( Collider2D other )
{
// Hit logic
if ( other . tag = = "AttackHitbox" | | other . tag = = "PickaxeHitbox" )
{
timerDmg = 0f ;
hit = false ;
}
}
#endregion
public void HandleState ( )
{
switch ( gameObject . GetComponent < NPC > ( ) . State )
{
case NPCStateEnum . Walking :
{
CheckDistance ( ) ;
break ;
}
case NPCStateEnum . Talking :
{
TalkingAction ( ) ;
break ;
}
case NPCStateEnum . Pending :
{
break ;
}
case NPCStateEnum . Attacking :
{
AttackingAction ( ) ;
break ;
}
default :
{
Debug . Log ( "Nieopisane zachowanie NPC ! ! !" ) ;
break ;
}
}
}
public bool IsInChassingRadious ( )
{
if ( Vector2 . Distance ( targetPosition . position , transform . position ) > = chasingRadius )
return false ;
return true ;
}
public bool IsInActionRadious ( )
{
if ( Vector2 . Distance ( targetPosition . position , transform . position ) > = attackingRadius )
return false ;
return true ;
}
public void SetActionAfterMetConditions ( )
{
gameObject . GetComponent < NPC > ( ) . State = NPCStateEnum . Attacking ;
}
public void TalkingAction ( )
{
// Not required in this script
}
public void AttackingAction ( )
{
// if during Attacking mode player GO OUT of the attacking radious
if ( ! IsInActionRadious ( ) )
{
gameObject . GetComponent < NPC > ( ) . State = NPCStateEnum . Walking ;
return ;
}
// Attacking logic
if ( firstAttack = = false )
{
if ( timerDmg > = 0.15f )
{
firstAttack = true ;
GameObject . FindGameObjectWithTag ( "Player" ) . GetComponent < Player > ( ) . TakeDamage (
gameObject . GetComponent < Enemy > ( ) . baseAttack ,
isPanelEnabled
) ;
timerDmg = 0f ;
}
}
if ( timerDmg > = waitTime )
{
timerDmg = 0f ;
GameObject . FindGameObjectWithTag ( "Player" ) . GetComponent < Player > ( ) . TakeDamage (
gameObject . GetComponent < Enemy > ( ) . baseAttack ,
isPanelEnabled
) ;
}
timerDmg + = Time . deltaTime ;
}
#region dupplicated from Following : )
public void TakeDamage ( float damage )
{
Debug . Log ( "TakeDamage" ) ;
gameObject . GetComponent < Enemy > ( ) . health - = damage ;
if ( gameObject . GetComponent < Enemy > ( ) . health < = 0 )
{
gameObject . SetActive ( false ) ;
gameObject . GetComponent < Enemy > ( ) . isKilled = 1 ;
GameObject . FindGameObjectWithTag ( "Player" ) . GetComponent < Player > ( ) . GetExp ( expValue ) ;
// pass info about killing assigned enemy to mission manager listener
// pass enemy name from script NOT object name (thats allow to have many different objects variantsa with this same aggregate key (private name - not preffab name) )
ConditionManager . Instance . UpdateKillCondition ( gameObject . GetComponent < Enemy > ( ) . MinionName ) ;
}
}
public void TakeKnockback ( )
{
Rigidbody2D enemy = gameObject . GetComponent < Rigidbody2D > ( ) ;
Rigidbody2D player = GameObject . FindGameObjectWithTag ( "Player" ) . GetComponent < Rigidbody2D > ( ) ;
if ( enemy ! = null )
{
enemy . isKinematic = false ;
Vector2 difference = enemy . transform . position - player . transform . position ;
difference = difference . normalized * thrust ;
enemy . AddForce ( difference , ForceMode2D . Impulse ) ;
//StartCoroutine(KnockCo(enemy));
}
}
#endregion
public void AfterAction ( )
{
approaching = false ;
isAfterAction = true ;
//isDuringConversation = false;
//PlayerPrefs.SetInt(gameObject.name + ".FirstDialogue", System.Convert.ToInt32(isAfterAction));
gameObject . GetComponent < NPC > ( ) . State = NPCStateEnum . Walking ;
}
}