// Use this for initialization public void Start() { bc = GetComponent <BaseController> (); if (bc == null) { Debug.LogError("Base Controller is null"); } ps = GameObject.FindObjectOfType <PlayerSpawner> (); if (ps == null) { Debug.LogError("Player Spawner is null"); } tm = GameObject.FindObjectOfType <TextManager> (); if (tm == null) { Debug.LogError("Text Manager is null"); } hitPoints = bc.GetHealth(); currentPoints = hitPoints; // @DEBUG(sdsmith): Add entry to debug overlay DebugOverlay.AddAttr("Max health", hitPoints.ToString()); DebugOverlay.AddAttr("Current health", currentPoints.ToString()); }
/** * Return true if the character is on the ground, false otherwise. */ private bool IsGrounded() { /* * @NOTE(sdsmith): There was issues with steep slopes when one ray was * shot downward from the center. The fix is shooting one ray every 90 * degrees of the circumference of the collider. * - 2017-02-13 * * @PERFORMANCE(sdsmith): Do we want to unroll this, short circuit it, * keep it the same? I perfer consistent timing for an operation this * common rather than fluctuating performance. However, it could be * argued that the general case is being on mostly level ground, which * would short ciruit it on the first of second ray. The downside is * you get a potential 4x slowdown on steep slopes. * - 2017-02-13 */ const float errorMargin = 0.5F; float colliderRadius = collider.radius; bool hit = false; for (float deltaX = -colliderRadius; deltaX <= colliderRadius; deltaX += 2 * colliderRadius) { for (float deltaZ = -colliderRadius; deltaZ <= colliderRadius; deltaZ += 2 * colliderRadius) { Vector3 delta = new Vector3(deltaX, 0, deltaZ); hit = hit || Physics.Raycast(transform.position + delta, -Vector3.up, errorMargin); //Debug.DrawRay(transform.position + delta, -Vector3.up * errorMargin, Color.yellow, 5); } } DebugOverlay.AddAttr("isGrounded", hit.ToString()); return(hit); }
protected void Start() { // Component references rigidbody = GetComponent <Rigidbody>(); collider = GetComponent <CapsuleCollider>(); audioSource = GetComponent <AudioSource>(); jumpSpeed = 5f; isJumping = IsGrounded(); isAirborn = isJumping; oldMoveInput = Vector3.zero; // @DEBUG(Llewellin): Add entry to debug overlay DebugOverlay.AddAttr("speed", GetSpeed().ToString()); DebugOverlay.AddAttr("damage", GetDamage().ToString()); }
[PunRPC] // can be called indirectly // all players recieve notification of something taking damage public virtual void TakeDamage(float amt, int attackerViewID) { currentPoints -= amt; // Play player damage notification if (gameObject.tag == "Player") { PlayerController pc = gameObject.GetComponent <PlayerController>(); Debug.Assert(pc != null, "Object tagged as 'Player' does not have a 'PlayerController'"); pc.PlayTakenDamageNotification(); } // @DEBUG(sdsmith): Update debug stats // @TODO(sdsmith): @PERFORMANCE(sdsmith): Should have these calls // wrapped under a debug flag to reduce performance impact of the // calls when the overlay is not enabled. //if (this.gameObject.GetComponent<PhotonView>().isMine) { DebugOverlay.AddAttr("Current health", currentPoints.ToString()); //} if (currentPoints <= 0) { Die(); SetStats(attackerViewID); SendKillMessage(attackerViewID); // Play kill sound for attacker PhotonView pv = PhotonView.Find(attackerViewID); if (pv) { // Player that hit this target is still alive, play the notification // @NOTE(sdsmith): If this is placed before 'Die()', players do not // die. Who knows. pv.gameObject.GetComponent <PlayerController>().PlayKillNotification(); } // Play death sound for killed player AudioClip clip = AudioClips.GetRand(AudioClips.playerDeath); AudioSource.PlayClipAtPoint(clip, this.gameObject.transform.position, 1.5f); } }
void Fire() { if (coolDown > 0) { return; } //changed if (gameObject.GetComponent <GrabAndDrop> ().GetGrabbedObject() != null) { return; } // Play fire/throw sound AudioClip clip = AudioClips.GetRand(AudioClips.playerThrow); audioSource.PlayOneShot(clip); // Fire the snowball if (fxManager != null) { // @DEBUG(sdsmith): Update debug stats DebugOverlay.AddAttr("snowballs fired count", (++firedSnowballsCount).ToString()); /* * @TODO(Llewellin): change the startPos to be where the snowball launches. * @NOTE(Llewellin): startPos is set forward slightly so the snowball doesn't come from the camera. * The camera is inside the player, which causes the snowball to hit us and causes complications in * SnowballController:onCollisionEnter(). * i.e. we collide with ourselves and take damage, then die */ // @TODO(sdsmith): Set offset of the snowball spawn location to be relative to the size of the player's // collider plus the width of the snowball collider and some error margin to make it change proof. Vector3 startPos = Camera.main.transform.position + (Camera.main.transform.forward * 1.1f); int playerViewID = this.gameObject.GetComponent <PhotonView>().viewID; fxManager.GetComponent <PhotonView>().RPC("SnowballFX", PhotonTargets.All, startPos, Camera.main.transform.rotation, snowballDamage, playerViewID); } coolDown = fireRate; }
void OnCollisionEnter(Collision collision) { // Play snowball impact sound // // @NOTE(sdsmith): Must use AudioSource.PlayClipAtpoint so the clip // persists after the destruction of the object. If we ere using an // AudioSource component, the clip would stop playing once that // component was destroyed. AudioClip impactClip = AudioClips.GetRand(AudioClips.snowballImpacts); AudioSource.PlayClipAtPoint(impactClip, transform.position); if (collision.gameObject.name == "Mountain") { // @NOTE(sdsmith): @PERFORMANCE(sdsmith): Note that 'Destroy' // delayed at least until the end of the frame update cycle. If we // hit the terrain, we know we don't need to do any additional // collision calculations. // // @TODO(sdsmith): This breaks Network manager when we take the advice // of the above comment and end the function here. Who knows. // - 2017-02-27 Destroy(this.gameObject); } // @DEBUG(sdsmith): Update debug overlay DebugOverlay.AddAttr("snowball collision count", (++nonTerrainCollisionCount).ToString()); Transform hitTransform = collision.transform; // If we hit something, lets resolve the hit if (hitTransform != null) { // Debug.Log ("HIT: " + collision.gameObject.name); Health h = hitTransform.GetComponent <Health>(); // check if the things parent has a Health object while (h == null && hitTransform.parent) { hitTransform = hitTransform.parent; h = hitTransform.GetComponent <Health>(); } // The thing we hit has a health component // Tell the thing we hit to take damage if (h != null) { PhotonView pv = h.GetComponent <PhotonView>(); if (pv == null) { Debug.Log("PlayerShooting: PhotonView is null"); } else { //get the thing that was hit PhotonPlayer target = pv.owner; // Get teams PunTeams.Team ourTeam = PhotonNetwork.player.GetTeam(); PunTeams.Team theirTeam = PunTeams.Team.none; // default objects to no team // Check if the target object has an owner // @NOTE(sdsmith): PhotonView.owner is null for scene objects // https://doc-api.photonengine.com/en/pun/current/class_photon_view.html#ad696cb93fb9835d633b9def970650edc if (target != null) { // Target has an owner (not a scene object), set its team theirTeam = target.GetTeam(); } if (ourTeam != theirTeam) { // Not targeting same team pv.RPC("TakeDamage", PhotonTargets.AllBuffered, damage, throwerViewID); // Play hit sound if our local client threw the snowball PhotonView throwerPV = PhotonView.Find(throwerViewID); if (throwerPV && Util.localPlayer == throwerPV.gameObject) { throwerPV.gameObject.GetComponent <PlayerController>().PlayHitNotification(); } } else { // Targeting same team } } } Destroy(this.gameObject); } }