private IEnumerator FinishThem() { UxChatController.SendToConsole(owner.playerName + "'s MushBoom", messageColor, "It's been a blast! #Laterz"); scaleDelay = 0; timeToScale = 10f; groundZero = GameObject.FindWithTag("groundZero"); Vector3 fixedSpot = new Vector3(100f, 15f, 100f); deformationKind = DeformationKind.groundZero; SingedMessages.SendPlayAudioClip("MushboomSound/mushboom_growth"); yield return(new WaitForSeconds(1f)); scaleTo *= 4f; nukeGreen.Emit(150); StartCoroutine(GrowTheShroom()); yield return(new WaitForSeconds(1f)); nukeIsReady.Invoke(); nukeGreen.Emit(150); nukeGreen.transform.localScale *= 2f; yield return(new WaitForSeconds(0.75f)); nukeGreen.Emit(200); yield return(new WaitForSeconds(1f)); nukeGreen.transform.localScale *= 2; nukeGreen.Emit(200); yield return(new WaitForSeconds(1.25f)); explosion.Play(); nukeGreen.Emit(200); yield return(new WaitForSeconds(4.5f)); Destroy(explosion); Destroy(nukeGreen); transform.position = fixedSpot; if (isServer) { PerformTerrainDeformation(groundZero); } Destroy(gameObject); }
private void PerformTerrainDeformation(GameObject terrain) { // perform terrain deformation (if terrain was hit) var terrainManager = terrain.GetComponent <TerrainDeformationManager>(); if (terrainManager != null) { var deformationPrefab = PrefabRegistry.singleton.GetPrefab <DeformationKind>(deformationKind); SingedMessages.SendPlayAudioClip( PrefabRegistry.GetResourceName <ProjectileSoundKind>(ProjectileSoundKind.projectile_explo)); //Debug.Log("CmdExplode instantiate deformation: " + deformationPrefab); GameObject deformation = Instantiate(deformationPrefab, gameObject.transform.position, Quaternion.identity) as GameObject; NetworkServer.Spawn(deformation); // determine deformation seed var seed = UnityEngine.Random.Range(1, 1 << 24); // execute terrain deformation on client terrainManager.RpcApplyDeform(deformation, seed); } }
IEnumerator NukeSequence() { SoundManager.instance.FadeOutForNuke(); // enable Nuke camera RpcViewNuke(); RpcToggleConsole(false); SingedMessages.SendPlayAudioClip("MushboomSound/mushboom_explo"); // find the nuke game object var nukeGO = GameObject.FindWithTag("nuke"); if (nukeGO == null) { Debug.Log("can't find nuke parent object"); yield break; } var nukeScript = nukeGO.GetComponent <NukeScript>(); // register ourselves as listener for nuke finished event nukeScript.onNukeFinished.AddListener(OnNukeFinished); // start nuke sequence on client RpcStartNuke(); // wait for nuke to be finished while (nukeActive) { yield return(null); } SingedMessages.SendPlayAudioClip("Voiceovers/voice_hi_mushboom_1"); yield return(new WaitForSeconds(4.25f)); SoundManager.instance.PlayMusicAfterNuke(); RpcToggleConsole(true); }
/// <summary> /// This is the state-engine driving the aim/power/shot control for the tank. /// Stay in this state until a shot is fired. /// NOTE: ensure that all yield calls are using next of frame (yield return null) to ensure proper input handling /// </summary> IEnumerator AimStateEngine() { // check to see if we still have availability for selected shot if (shotInventory.GetAvailable(selectedShot) <= 0) { selectedShot = shotInventory.NextAvailableShot(selectedShot); Debug.Log("now using shot: " + selectedShot); } // Debug.Log("AimStateEngine called for " + this.name + " with isServer: " + isServer + " and hasControl: " + hasControl); // continue while we have control while (hasControl) { if (EventSystem.current.currentSelectedGameObject != null && EventSystem.current.currentSelectedGameObject.tag == "inputexclusive") { yield return(null); continue; } // FlyCam Controls if (FlyCam.self.isEnabled) { if (Input.GetKeyDown(KeyCode.KeypadPlus)) { FlyCam.self.ZoomIn(); } else if (Input.GetKeyDown(KeyCode.KeypadMinus)) { FlyCam.self.ZoomOut(); } if (Input.GetKey(KeyCode.I)) { FlyCam.self.MoveForward(); } else if (Input.GetKey(KeyCode.K)) { FlyCam.self.MoveBack(); } if (Input.GetKey(KeyCode.J)) { FlyCam.self.MoveLeft(); } else if (Input.GetKey(KeyCode.L)) { FlyCam.self.MoveRight(); } if (Input.GetKey(KeyCode.U)) { FlyCam.self.MoveUp(); } else if (Input.GetKey(KeyCode.O)) { FlyCam.self.MoveDown(); } if (Input.GetKey(KeyCode.Keypad8)) { FlyCam.self.RotateUp(); } else if (Input.GetKey(KeyCode.Keypad2)) { FlyCam.self.RotateDown(); } if (Input.GetKey(KeyCode.Keypad4)) { FlyCam.self.RotateLeft(); } else if (Input.GetKey(KeyCode.Keypad6)) { FlyCam.self.RotateRight(); } if (Input.GetKey(KeyCode.Keypad1)) { FlyCam.self.TiltLeft(); } else if (Input.GetKey(KeyCode.Keypad3)) { FlyCam.self.TiltRight(); } } // End FlyCam Controls // handle power up/down if (Input.GetKeyDown(KeyCode.RightBracket) || Input.GetKeyDown(KeyCode.LeftBracket) || Input.GetKeyDown(KeyCode.E) || Input.GetKeyDown(KeyCode.Q)) { SingedMessages.SendStartAudioLoop( gameObject, "PowerAudio", TankSoundKind.tank_power_UpDown_LOOP); } if (Input.GetKeyUp(KeyCode.RightBracket) || Input.GetKeyUp(KeyCode.LeftBracket) || Input.GetKeyUp(KeyCode.E) || Input.GetKeyUp(KeyCode.Q)) { SingedMessages.SendStopAudioLoop( gameObject, "PowerAudio"); } if (Input.GetKey(KeyCode.RightBracket) || Input.GetKey(KeyCode.E)) { var magnifier = (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) ? 3f : 1f; shotPower += magnifier * shotPowerModifier; } if (Input.GetKey(KeyCode.LeftBracket) || Input.GetKey(KeyCode.Q)) { var magnifier = (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) ? 3f : 1f; shotPower -= magnifier * shotPowerModifier; } shotPower = Mathf.Clamp(shotPower, 0f, maxShotPower); // handle changing shot if (Input.GetKeyDown(KeyCode.Comma) || Input.GetKeyDown(KeyCode.X)) { selectedShot = shotInventory.PrevAvailableShot(selectedShot); Debug.Log("now using shot: " + selectedShot); } if (Input.GetKeyDown(KeyCode.Period) || Input.GetKeyDown(KeyCode.C)) { selectedShot = shotInventory.NextAvailableShot(selectedShot); Debug.Log("now using shot: " + selectedShot); } // Shoot already ... when shot is fired, finish this coroutine; if (Input.GetKeyDown(KeyCode.Space)) { //Debug.Log("space is down, calling CmdFire"); // sanity check for ammo SingedMessages.SendStopAudioLoop( gameObject, "PowerAudio"); SingedMessages.SendStopAudioLoop( gameObject, "HorizontalMovementAudio"); SingedMessages.SendStopAudioLoop( gameObject, "VerticalMovementAudio"); if (shotInventory.GetAvailable(selectedShot) > 0) { SingedMessages.SendPlayAudioClip(tankSoundKind); speech = BarkManager.self.GetTheShotOneLinerPath(selectedShot, charVoice); SingedMessages.SendPlayAudioClip(speech, false, 0.75f); CmdFire(shotPower, selectedShot); // decrease ammo count shotInventory.ServerModify(selectedShot, -1); // check to see if we still have availability for selected shot if (shotInventory.GetAvailable(selectedShot) <= 0) { selectedShot = shotInventory.NextAvailableShot(selectedShot); Debug.Log("now using shot: " + selectedShot); } } else { Debug.Log("out of ammo for shottype " + selectedShot); } yield break; } if (Input.GetKeyDown(KeyCode.O)) { speech = BarkManager.self.GetTheShotOneLinerPath(selectedShot, charVoice); } // handle horizontal turret movement var newRotation = Input.GetAxis("Horizontal"); if (!Mathf.Approximately(newRotation, 0f)) { if (!isHorizontalAxisInUse) { SingedMessages.SendStartAudioLoop( gameObject, "HorizontalMovementAudio", TankSoundKind.tank_movement_LeftRight_LOOP_01); isHorizontalAxisInUse = true; } } else { if (isHorizontalAxisInUse) { SingedMessages.SendStopAudioLoop( gameObject, "HorizontalMovementAudio"); isHorizontalAxisInUse = false; } } if (model != null) { model.tankRotation += newRotation * Time.deltaTime * rotationSpeedVertical; } // handle vertical turret movement var newElevation = Input.GetAxis("Vertical"); if (!Mathf.Approximately(newElevation, 0f)) { if (!isVerticalAxisInUse) { SingedMessages.SendStartAudioLoop( gameObject, "VerticalMovementAudio", TankSoundKind.tank_movement_UpDown_LOOP_01); isVerticalAxisInUse = true; } } else { if (isVerticalAxisInUse) { SingedMessages.SendStopAudioLoop( gameObject, "VerticalMovementAudio"); isVerticalAxisInUse = false; } } if (model != null) { model.turretElevation += newElevation * Time.deltaTime * rotationSpeedHorizontal; model.turretElevation = Mathf.Clamp(model.turretElevation, minTurretElevation, maxTurretElevation); } // continue on next frame yield return(null); } }
// hook into NetManagers server setup process public override void OnStartServer() { base.OnStartServer(); //base is empty SingedMessages.ServerRegisterMessageHandlers(); }
// ------------------------------------------------------ // EVENT HANDLER METHODS // hook into NetworkManager client setup process public override void OnStartClient(NetworkClient mClient) { base.OnStartClient(mClient); // base implementation is currently empty SingedMessages.ClientRegisterMessageHandlers(mClient); }
// ------------------------------------------------------ // SERVER-ONLY METHODS /// <summary> /// Generate explosion and apply damage for projectile /// </summary> void ServerExplode(Collision collision) { //Debug.Log("ServerExplode: " + this); // Get list of colliders in range of this explosion // FIXME: range of projectile shouldn't be hard-coded Collider[] flakReceivers = Physics.OverlapSphere(transform.position, effectRadius); // keep track of list of root objects already evaluated var hitList = new List <GameObject>(); foreach (Collider flakReceiver in flakReceivers) { var rootObject = flakReceiver.transform.root.gameObject; // has this object already been hit by this projectile? if (!hitList.Contains(rootObject)) { hitList.Add(rootObject); GameObject gameObjRef = flakReceiver.gameObject; //Debug.Log("hit gameObject: " + rootObject.name); // Debuff TankController tankObj = rootObject.GetComponent <TankController>(); if (tankObj != null) { tankObj.SetAreaOfEffect(areaOfEffect); } // potentially apply damage to any object that has health component var health = rootObject.GetComponent <Health>(); if (health != null) { //Debug.Log (rootObject.name + " received splash damage"); Vector3 cannonballCenterToTankCenter = transform.position - gameObjRef.transform.position; //Debug.Log (string.Format ("cannonball position: {0}, tank position: {1}", transform.position, gameObjRef.transform.position)); //Debug.Log (string.Format ("cannonballCenterToTankCenter: {0}", cannonballCenterToTankCenter)); // Some projectiles have AoE > 10, so damage radius needs to be clamped float hitDistToTankCenter = Mathf.Min(10f, cannonballCenterToTankCenter.magnitude); //Debug.Log ("Distance to tank center: " + hitDistToTankCenter); // NOTE: The damagePoints formula below is taken from an online quadratic regression calculator. The idea // was to plug in some values and come up with a damage computation formula. The above formula yields: // direct hit (dist = 0m): 100 hit points // Hit dist 5m: about 25 hit points // hit dist 10m: about 1 hit point // The formula is based on a max proximity damage distance of 10m int damagePoints = (int)(1.23f * hitDistToTankCenter * hitDistToTankCenter - 22.203f * hitDistToTankCenter + 100.012f); switch (myKind) { case ProjectileKind.cannonBall: damagePoints /= 2; break; case ProjectileKind.acorn: damagePoints = (int)(damagePoints * 1.5); break; case ProjectileKind.artilleryShell: if (tankObj != null && tankObj.hasVirus == false) { tankObj.InfectPlayer(rootObject); damagePoints = 20; } break; case ProjectileKind.mushboom: damagePoints += (int)(effectRadius * 0.5); break; } if (damagePoints > 0) { if (tankObj == null || !tankObj.hasControl) { health.TakeDamage(damagePoints, (shooter != null) ? shooter.gameObject : null); } else { health.RegisterDelayedDamage(damagePoints, (shooter != null) ? shooter.gameObject : null); } SingedMessages.SendPlayAudioClip( PrefabRegistry.GetResourceName <ProjectileSoundKind>(ProjectileSoundKind.tank_hit)); //Debug.Log ("Damage done to " + rootObject.name + ": " + damagePoints + ". Remaining: " + health.health); // Do shock displacement // if target has rigidbody, apply displacement force to rigidbody var rigidbody = rootObject.GetComponent <Rigidbody>(); if (rigidbody != null && rootObject.name != "mushMine(Clone)") { Vector3 displacementDirection = cannonballCenterToTankCenter.normalized; //Debug.Log (string.Format ("Displacement stats: direction={0}, magnitude={1}", displacementDirection, damagePoints)); rigidbody.AddForce(rigidbody.mass * (displacementDirection * damagePoints * 0.8f), ForceMode.Impulse); // Force = mass * accel } } } } } if (shooter != null) { shooter.GetComponent <Health>().TakeDelayedDamage(); } PerformTerrainDeformation(collision.gameObject); if (spawnMush) { LayMushMine(); } CreateExplosion(); }