string UpdateServer_MOVING() { if (EventMoveEnd()) { return("IDLE"); } if (EventTargetDied()) { target = null; agent.ResetMovement(); return("IDLE"); } if (EventTargetTooFarToFollow()) { target = null; agent.speed = walkSpeed; agent.stoppingDistance = 0; agent.destination = startPosition; return("MOVING"); } if (EventTargetTooFarToAttack() || IsTargetInRangeButNotReachable()) { agent.speed = runSpeed; agent.stoppingDistance = 0; agent.destination = target.collider.ClosestPoint(transform.position); return("MOVING"); } if (EventAggro()) { Collider targetCollider = target.collider; if (Vector3.Distance(transform.position, targetCollider.ClosestPoint(transform.position)) <= attackRange * attackToMoveRangeRatio && Utils.IsReachableVertically(collider, targetCollider, attackRange)) { attackEndTime = NetworkTime.time + attackInterval; agent.ResetMovement(); RpcOnAttackStarted(); return("ATTACKING"); } } if (EventAttackFinished()) { } if (EventTargetDisappeared()) { } if (EventMoveRandomly()) { } return("MOVING"); }
void TargetResetMovement(Vector3 resetPosition) { // reset path and velocity //Debug.LogWarning(name + "(local=" + isLocalPlayer + ") TargetResetMovement @ " + resetPosition); agent.ResetMovement(); agent.Warp(resetPosition); }
void Update() { if (isServer) { bool hasPath = HasPath(); if (hasPath && agent.destination != lastSerializedDestination) { SetDirtyBit(1); } else if (!hasPath && agent.velocity != lastSerializedVelocity) { SetDirtyBit(1); } else if (!hasPath && Vector3.Distance(transform.position, lastUpdatePosition) > agent.speed) { RpcWarped(transform.position); } else if (hadPath && !hasPath) { SetDirtyBit(1); } lastUpdatePosition = transform.position; hadPath = hasPath; lastUpdatePosition = transform.position; } else if (isClient) { if (requiredVelocity != Vector3.zero) { agent.ResetMovement(); agent.velocity = requiredVelocity; LookAtY(transform.position + requiredVelocity); } } }
public void TargetResetMovement(NetworkConnection conn, Vector3 resetPosition) { // reset path and velocity //Debug.Log(name + " TargetResetMovement @ " + resetPosition); agent.ResetMovement(); agent.Warp(resetPosition); }
protected virtual void OnDeath() { // clear movement/buffs/target/cast agent.ResetMovement(); buffs.Clear(); target = null; currentSkill = -1; // addon system hooks Utils.InvokeMany(typeof(Entity), this, "OnDeath_"); }
void TargetResetMovement(NetworkConnection conn) { if (entity.GetType() == typeof(Player)) { entity.m_speed = 0; } else { // reset path and velocity agent.ResetMovement(); } }
void Update() { if (isServer) { // detect move mode bool hasPath = HasPath(); // click movement and destination changed since last sync? if (hasPath && agent.destination != lastSerializedDestination) { //Debug.LogWarning(name + " dirty because destination changed from: " + lastSerializedDestination + " to " + agent.destination + " hasPath=" + agent.hasPath + " pathPending=" + agent.pathPending); SetDirtyBit(1); } // wasd movement and velocity changed since last sync? else if (!hasPath && agent.velocity != lastSerializedVelocity) { //Debug.LogWarning(name + " dirty because velocity changed from: " + lastVelocity + " to " + agent.velocity); SetDirtyBit(1); } // neither click or wasd movement, but position changed further than 'speed'? // then we must have teleported, no other way to move this fast. else if (!hasPath && Vector3.Distance(transform.position, lastUpdatePosition) > agent.speed) { // warp detection is just about 100% correct, so let's send a // Rpc to warp the client and not leave it up to OnDeserialize's // guess wether or not we warped. this is worth it for corerctness. //Debug.Log(name + " teleported from: " + lastUpdatePosition + " to: " + transform.position); RpcWarped(transform.position); } lastUpdatePosition = transform.position; } else if (isClient) { // apply velocity constantly, not just in OnDeserialize // (not on host because server handles it already anyway) if (requiredVelocity != Vector3.zero) { agent.ResetMovement(); // needed after click movement before we can use .velocity agent.velocity = requiredVelocity; LookAtY(transform.position + requiredVelocity); // velocity doesn't set rotation } } }
void Update() { if (isServer) { // detect move mode bool hasPath = HasPath(); // click movement and destination changed since last sync? if (hasPath && agent.destination != lastSerializedDestination) { //Debug.LogWarning(name + " dirty because destination changed from: " + lastSerializedDestination + " to " + agent.destination + " hasPath=" + agent.hasPath + " pathPending=" + agent.pathPending); SetDirtyBit(1); } // wasd movement and velocity changed since last sync? else if (!hasPath && agent.velocity != lastSerializedVelocity) { //Debug.LogWarning(name + " dirty because velocity changed from: " + lastVelocity + " to " + agent.velocity); SetDirtyBit(1); } // NOTE: no automatic warp detection. // Entity.Warp calls RpcWarped for 100% reliable detection. // // neither of those, but had path before and not anymore now? // then agent.Reset must have been called else if (hadPath && !hasPath) { //Debug.LogWarning(name + " agent.Reset detected"); SetDirtyBit(1); } hadPath = hasPath; } else if (isClient) { // apply velocity constantly, not just in OnDeserialize // (not on host because server handles it already anyway) if (requiredVelocity != Vector3.zero) { agent.ResetMovement(); // needed after click movement before we can use .velocity agent.velocity = requiredVelocity; LookAtY(transform.position + requiredVelocity); // velocity doesn't set rotation } } }
void TargetResetMovement(NetworkConnection conn) { // reset path and velocity agent.ResetMovement(); }
string UpdateMOVING() { // events sorted by priority (e.g. target doesn't matter if we died) if (EventMoveEnd()) { // we reached our destination. return("IDLE"); } if (EventTargetDied()) { // we had a target before, but it died now. clear it. target = null; agent.ResetMovement(); return("IDLE"); } if (EventTargetTooFarToFollow()) { // we had a target before, but it's out of follow range now. // clear it and go back to start. don't stay here. target = null; agent.speed = walkSpeed; agent.stoppingDistance = 0; agent.destination = startPosition; return("MOVING"); } if (EventTargetTooFarToAttack()) { // we had a target before, but it's out of attack range now. // follow it. (use collider point(s) to also work with big entities) agent.speed = runSpeed; agent.stoppingDistance = attackRange * attackToMoveRangeRatio; agent.destination = target.GetComponentInChildren <Collider>().ClosestPoint(transform.position); return("MOVING"); } if (EventTargetUnreachable()) { // we have a target in attack range, but it's behind a door or wall return("IDLE"); } if (EventAggro()) { // the target is close, but we are probably moving towards it already // so let's just move a little bit closer into attack range so that // we can keep attacking it if it makes one step backwards if (Vector3.Distance(transform.position, target.GetComponentInChildren <Collider>().ClosestPoint(transform.position)) <= attackRange * attackToMoveRangeRatio) { // target in attack range. try to attack it // -> start attack timer and go to casting // (we may get a target while randomly wandering around) attackEndTime = Time.time + attackInterval; agent.ResetMovement(); OnAttackStarted(); return("ATTACKING"); } } if (EventAttackFinished()) { } // don't care if (EventTargetDisappeared()) { } // don't care if (EventMoveRandomly()) { } // don't care return("MOVING"); // nothing interesting happened }