/// <summary> /// Gets the list of photonviews of non-player AI characters /// </summary> /// <returns>The P vs.</returns> /// <param name="checkAlive">If set to <c>true</c> only returns alive character</param> public static List <PhotonView> Get_PVs(bool checkAlive = false) { List <PhotonView> AICharacterPVs = new List <PhotonView> (); PHOTON_VIEW_LIST.RemoveAll(x => x == null); foreach (var p in PHOTON_VIEW_LIST) { CharacterStatusHandler csh = p.GetComponent <CharacterStatusHandler> (); if (csh != null) { // if (csh is AIStatusHandler) { if (csh.Type == TYPE.NON_PLAYER_AI) { if (checkAlive && !csh.Alive()) { //if checkalive and dead, don't add this one continue; } else { AICharacterPVs.Add(p); } } } else { Debug.Log("WARNING : Element of this list must have CharacterStatusHandler as its component"); } } return(AICharacterPVs); }
//dev //collider attached to the rig seems to be spinning like hell //Thus force-prevent spinning // void LateUpdate () // { // transform.localPosition = Vector3.zero; // transform.localRotation = Quaternion.identity; // // else // // print ("osh : " + _osh.name); // } // void OnCollisionStay (Collision collision) // { //// print ("Collided with " + collision.transform.name); // //damagable things discovered //// if (collision.transform.GetComponent<ObjectStatusHandler> () != null) { //// ObjectStatusHandler osh = collision.transform.GetComponent<ObjectStatusHandler> (); //// if (osh.IsWalled) { //// foreach (var po in _pressingObjects) { //// if (po.Timer + _damagingRate < Time.time) { //// dealDamange (osh); //// } //// } //// } ////// print (osh.name); //// origin = osh.transform.position; //// origin = new Vector3 (origin.x, transform.position.y, origin.z); //// dir = osh.transform.position - collision.contacts [0].point; //// dir = new Vector3 (dir.x, 0f, dir.z); //// dir.Normalize (); //// //// // Physics.SphereCast (레이저를 발사할 위치, 구의 반경, 발사 방향, 충돌 결과, 최대 거리) //// LayerMask lm = (1 << LayerHelper.DEFAULT); //// isHit = false; ////// isHit = Physics.SphereCast (origin, radius, dir, out hit, maxDistance, lm); //// isHit = Physics.Raycast (origin, dir, out hit, maxDistance, lm); //// if (isHit) { //// print ("Hit : " + hit.collider.name); //// dealDamange (osh); ////// Debug.Break (); //// ParticleController.PC.InstantiateParticle(collision.contacts [0].point); //// } //// } // } // void OnDrawGizmos () // { // if (isHit) { // Gizmos.color = Color.red; // Gizmos.DrawRay (origin, dir * hit.distance); //// Gizmos.DrawWireSphere (origin + dir * hit.distance, radius); // } else { // Gizmos.DrawRay (origin, dir * maxDistance); // } // } /// <summary> /// Handles dealing damage to the contact object(enemy) /// Also handles pushback and staggering the target. /// dev /// </summary> /// <param name="osh">Target's ObjectStatusHandler</param> protected void dealDamange(ObjectStatusHandler osh) { //inflict damage osh.SubtractHealth(_damage); //disable hit target's damaging points if (true) { if (osh.GetComponent <CombatHandler> ()) { // disableDamagingPoints (osh.GetComponent<CombatHandler> ()); osh.GetComponent <CombatHandler> ().DisableDamagingPoints(); } } //add to ultimate guage _ch.AddUltimatePoint(_damage / 25); //add more if it's a killing blow if (osh.GetHealth() - _damage <= 0) { _ch.AddUltimatePoint(5); } //if character, stagger it //Note : Stagger animation will transit from AnyState for minions and certain character via animator // Player characters at the moment does not have AnyState linked to Stagger, so their action will not get interrupted by getting attack CharacterStatusHandler csh = osh.GetComponent <CharacterStatusHandler> (); if (csh != null) { csh.Stagger(_damagingRate / 5f); } // if (csh != null) // ((CharacterStatusHandler)osh).Stagger (_pushDuration); }
void Start() { _ch = GetComponent <CombatHandler> (); _aimh = GetComponent <AIMovementHandler> (); _csh = GetComponent <CharacterStatusHandler> (); //dev // InvokeRepeating ("Scan", 1f, _scanInterval); }
/// <summary> /// Handles dealing damage to the contact object(enemy) /// Also handles pushback and staggering the target. /// </summary> /// <param name="osh">Target's ObjectStatusHandler</param> protected void dealDamange(ObjectStatusHandler osh) { //inflict damage osh.SubtractHealth(_weapon.GetDamage()); //disable hit target's damaging points if (_weapon.GetDisablesTargetDamagingPointOnhit()) { if (osh.GetComponent <CombatHandler> ()) { // disableDamagingPoints (osh.GetComponent<CombatHandler> ()); osh.GetComponent <CombatHandler> ().DisableDamagingPoints(); } } //add to ultimate guage _weapon.GetOwner().AddUltimatePoint(_weapon.GetDamage() / 25); //add more if it's a killing blow if (osh.GetHealth() - _weapon.GetDamage() <= 0) { _weapon.GetOwner().AddUltimatePoint(5); } //drop if hanging CharacterMovementHandler cmh = osh.GetComponent <CharacterMovementHandler> (); // HangHandler hh = cmh.HangHandler; if (cmh && cmh.Hanging) { // hh.HangToDrop (); cmh.HangToDrop(); } else { //push object back //Duke (8/6/2016) //BUG : disabled because push direction changes as target rotates. make it absolute direction //Log : //Duke(8/11/2016) : Code is correct, suspect problem with pre-existing photon view enemies. Instantiating all characters may solve it. Enabled pushback to test it. //Duke(8/27/2016) : Problem occured again, there must be something wrong // Seems to be fixed with setting position i nstead of translate pushBack(osh, _pushDuration); //if character, stagger it //Note : Stagger animation will transit from AnyState for minions and certain character via animator // Player characters at the moment does not have AnyState linked to Stagger, so their action will not get interrupted by getting attack CharacterStatusHandler csh = osh.GetComponent <CharacterStatusHandler> (); if (csh != null) { // csh.Stagger (_pushDuration); csh.Stagger(_staggerDuration); } } }
void OnTriggerExit(Collider other) { CharacterStatusHandler _chr = other.GetComponent <CharacterStatusHandler> (); if (_chr != null) { if (_chrInArea.Contains(_chr)) { _chrInArea.Remove(_chr); } } }
// /// <summary> // /// Gets the roaming position. // /// Ex. If there is no valid attack position available, roam in roaming position // /// </summary> // /// <returns>The roaming position.</returns> // /// <param name="target">Target.</param> // public Vector3? GetRoamingPosition (CharacterStatusHandler target = null) // { // Vector3? roamingPosition = null; // // //if target not specified, use current target // if (target == null) { // if (this.Target != null) { // target = this.Target; // } else { // //if current target doesn't exist, scan // if (Scan () != null) { // target = this.Target; // } else { // //no target available // return null; // } // } // } // // //look for position // // return roamingPosition; // } /// <summary> /// Gets 6 evenly spaced position slots around the target /// </summary> /// <returns>The position slots around target</returns> /// <param name="distance">Distance to the slots, from target</param> /// <param name="target">Target.</param> /// <param name="getOnlyMovableSlots">Whether to check and get movable slots(excluding occupied or inaccecible positions)</param> public List <Vector3> GetPositionSlots(float distance, CharacterStatusHandler target = null, bool getOnlyMovableSlots = true) { List <Vector3> slots = new List <Vector3> (); //if target not specified, use current target if (target == null) { if (this.Target != null) { target = this.Target; } else { //if current target doesn't exist, scan if (Scan() != null) { target = this.Target; } else { //no target available return(slots); } } } //parametric equation for a circle(center (cx,cz)) //x = cx + r * cos(a) //z = cz + r * sin(a) //r = distance //get 6 slots(positions) around the target float cx = target.transform.position.x; float cy = target.transform.position.y; //Note : How will this affect in slope?s float cz = target.transform.position.z; float a = 60f; int count = 360 / (int)a; for (int i = 0; i < count; i++) { slots.Add(new Vector3(cx + distance * Mathf.Cos(i * a * Mathf.Deg2Rad), cy, cz + distance * Mathf.Sin(i * a * Mathf.Deg2Rad))); } return(slots); }
public Character(CharacterTemplateSlot templateSlot, Team team, CharacterActor actor, CharacterMover mover, CharacterFloatingTextHandler floatingTextHandler) { Template = templateSlot.Template; actor.Owner = this; mover.Owner = this; floatingTextHandler.Owner = this; Team = team; Actor = actor; Mover = mover; FloatingTextHandler = floatingTextHandler; ActionPointHandler = new CharacterActionPointHandler(this); PositionHandler = new CharacterPositionHandler(this, templateSlot.Position); AbilityHandler = new CharacterAbilityHandler(this); EventHandler = new CharacterEventHandler(this); StatusHandler = new CharacterStatusHandler(this); HealthHandler = new CharacterHealthHandler(this); AIHandler = new CharacterAIHandler(this); RegisterAvailabilityListeners(); }
/// <summary> /// Scan for visible enemy /// </summary> public CharacterStatusHandler Scan() { CharacterStatusHandler foundTarget = null; CharacterStatusHandler tempTarget = null; //direction from eyeposition to target Vector3 dir; // //dev // //performance test between loop order and raycast // float startTime = Time.time; //cache List <CombatHandler> enemies = CombatHandler.GET_ENEMIES(_ch.GetTeam(), true); if (!_checkClosest) { enemies.Shuffle(); } //get all enemies in range foreach (var ch in enemies.Where(x => Vector3.Distance(x.transform.position, this.transform.position) < _rangeOfVision && //Check if target are in range of vision Vector3.Angle(transform.forward, x.transform.position - this.transform.position) < _angleOfVision / 2f //Check if target are in angle of vision(Field of vision) )) { //check visibility with raycast LayerMask layerMask = 1 << LayerHelper.COMMON_BODY; RaycastHit hit; if (Physics.Raycast(_eyePosition.position , ch.transform.position - transform.position //Direction from eye to target , out hit, _rangeOfVision + 1f , layerMask )) { tempTarget = ch.GetComponent <CharacterStatusHandler> (); //get closest if (_checkClosest && (foundTarget == null || Vector3.Distance(foundTarget.transform.position, this.transform.position) > Vector3.Distance(tempTarget.transform.position, this.transform.position))) { foundTarget = tempTarget; } else { if (tempTarget != null) { print("scanned : " + tempTarget.name); } //otherwise, get random Target = tempTarget; return(tempTarget); } } } //dev // if (foundTarget != null) { // print ("scanned : " + foundTarget.name); // } //if nothing found, do nearcheck if (foundTarget == null) { foreach (var ch in enemies.Where(x => Vector3.Distance(x.transform.position, this.transform.position) < _nearRoV //Check if target are in range of vision )) { tempTarget = ch.GetComponent <CharacterStatusHandler> (); //get closest if (_checkClosest && (foundTarget == null || Vector3.Distance(foundTarget.transform.position, this.transform.position) > Vector3.Distance(tempTarget.transform.position, this.transform.position))) { foundTarget = tempTarget; } else { if (tempTarget != null) { print("scanned : " + tempTarget.name); } //otherwise, get random Target = tempTarget; return(tempTarget); } } } Target = tempTarget; return(foundTarget); }
/// <summary> /// Gets the attack position of a target /// Note : Only supports melee attack position for now /// </summary> /// <returns>The attack position.</returns> /// <param name="target">Target.</param> /// <param name="distance">Distance.</param> public Vector3?GetAttackPosition(CharacterStatusHandler target = null) //, float distance = 2f) { // Vector3? attackPosition = null; AIMovementHandler.PositionSlot ps = null; //if target not specified, use current target if (target == null) { if (this.Target != null) { target = this.Target; } else { //if current target doesn't exist, scan if (Scan() != null) { target = this.Target; } else { //no target available return(null); } } } //look for position // foreach (var pos in GetPositionSlots(distance, target)) { foreach (var slot in target.GetComponent <AIMovementHandler>().MeleeSlots) { //check if position is movable if (!_aimh.IsCellWalkable(slot.POS)) { continue; } else { if (slot.CHS != null) { //if slot has been mine, clear it if (slot.CHS == _csh) { slot.CHS = null; } else { //slot is taken, possibly take it away if this is closer if ((Vector3.Distance(slot.POS, slot.CHS.transform.position) <= Vector3.Distance(slot.POS, transform.position))) { continue; } else if (Vector3.Distance(slot.CHS.transform.position, target.transform.position) <= Vector3.Distance(this.transform.position, target.transform.position)) { //if slot owner is further away from the point, but closer to the target, don't take it continue; } } } if (ps == null) { ps = slot; ps.CHS = _csh; } else if (Vector3.Distance(this.transform.position, ps.POS) > Vector3.Distance(this.transform.position, slot.POS)) { //get new attack position if it's available and closer ps.CHS = null; ps = slot; ps.CHS = _csh; } } } if (ps == null) { return(null); } else { return(ps.POS); } }
protected virtual void OnTriggerEnter(Collider collider) { if (_isActive) { // print (collider.name); //When hitting hitbox if (collider.GetComponent <Hitbox> () != null) { Hitbox hb = collider.GetComponent <Hitbox> (); foreach (var l in _damagableLayers) { // print (l.ToString () + ", " + LayerHelper.HITBOX_TEAM_5.ToString () + ", " + collider.name); if (collider.gameObject.layer == l) { ObjectStatusHandler osh = collider.GetComponent <Hitbox> ().GetOSH(); //When hitting blocking point if (hb is BlockingPoint) { // print ("BLOCK"); //disable this character's damaging points _weapon.GetOwner().DisableDamagingPoints(); // _collider.enabled = false; // Debug.Break (); //stagger this character //Note : need a way to stagger player characters as it's controlled by minion's animator for now CharacterStatusHandler csh = _weapon.GetOwner().GetComponent <CharacterStatusHandler> (); //delay blocked staggering for fine-tuning float staggerDelay = 0.1f; if (csh != null) { csh.Stagger(((BlockingPoint)hb).GetStaggerDuration(), staggerDelay); } //instantiate particles //need to change to different particle to differentiate blocking vs damaging ParticleController.PC.InstantiateParticle(ParticleController.PARTICLE_TYPE.HIT, collider.transform.position, staggerDelay); //play sound SoundManager.SINGLETON.PlayHitSound(_weapon.Type, SoundManager.HitResult.Blocked, collider.transform.position); // Debug.Break (); } else if (osh) { if (osh is BridgeStatusHandler && RoomLevelHelper.PLAYER_CLASS != CHARACTER_CLASS.TANK) { return; } // print ("hit : " + osh.name); if (!_OSHList.Contains(osh)) { dealDamange(osh); hitEffect(collider.transform.position); ParticleController.PC.InstantiateParticle(ParticleController.PARTICLE_TYPE.HIT, collider.transform.position); _OSHList.Add(osh); } else if (!_isOneTimeDamage) { dealDamange(osh); hitEffect(collider.transform.position); ParticleController.PC.InstantiateParticle(ParticleController.PARTICLE_TYPE.HIT, collider.transform.position); } } else { print(collider.name); } //play sound SoundManager.SINGLETON.PlayHitSound(_weapon.Type, SoundManager.HitResult.Hit, collider.transform.position); } } } } }
public PositionSlot() { CHS = null; POS = Vector3.zero; }
/// <summary> /// Initializes a new instance of the <see cref="AIStatusHandler+PositionSlot"/> struct. /// </summary> /// <param name="chs">Character in this slot</param> /// <param name="pos">Position of this slot</param> public PositionSlot(Vector3 pos, CharacterStatusHandler chs = null) { CHS = chs; POS = pos; }