public void CorrectPosition(int lastControlCommandApplied, Vector3 correctPosition, Vector3 correctMomentum, float correctDirection, Vector3 correctVelocity, float crouch_factor) { ////Debug.Log (MyPlayer.networkView.viewID + ") " + "Correcting my position"); LastCorrectionRespondedTo = lastControlCommandApplied; // 12A: Reposition the player to match when the server sent the correction MyPlayer.transform.position = correctPosition; MyPlayer.state.angle = correctDirection; SceneCharacter3D p = (SceneCharacter3D)MyPlayer; p.state.pos = correctPosition; p.state.momentum = correctMomentum; p.state.angle = correctDirection; p.state.velocity = correctVelocity; p.crouch_factor = crouch_factor; // 12B: Make up for control commands which were sent between when the server sent the correction and now ////Debug.Log (MyPlayer.networkView.viewID + ") " + "Applying missing commands, starting with " + (lastControlCommandApplied + 1) + ", up to " + CurrentControlCommandId); while (ControlCommands.ContainsKey(lastControlCommandApplied + 1)) { Debug.Log(MyPlayer.GetComponent <NetworkView>().viewID + ") " + "Applying CC " + lastControlCommandApplied + 1); MyPlayer.ExecuteControlCommand(ControlCommands[lastControlCommandApplied + 1]); lastControlCommandApplied++; } UpdateCamera(); }
void fire_plasma(SceneCharacter3D character) { if (!character.can_fire_plasma()) { return; } Projectiles.Add(Plasma.Fire(character, plasma_prefab)); }
void fire_grenade(SceneCharacter3D character) { if (character.grenades < 1) { return; } //character.grenades--; Projectiles.Add(Grenade.Fire(character, grenade_prefab)); }
public void ValidatePosition(int lastCorrectionRepondedTo, int lastControlApplied, Vector3 clientPosition, float clientAngle, NetworkMessageInfo info) { Player player = Players[info.sender.guid]; // 11B: Make sure the client has used the last correction we sent if (lastCorrectionRepondedTo < player.LastCorrectionSent) { return; } #region 11C: Get the difference between the player's state and the server's ObjectState serverStateAfterControl = player.StatesAfterControls[lastControlApplied]; if (serverStateAfterControl == null) { return; } XDiff = clientPosition.x - serverStateAfterControl.Position.x; YDiff = clientPosition.y - serverStateAfterControl.Position.y; ZDiff = clientPosition.z - serverStateAfterControl.Position.z; //XAngDiff = clientDirection.x - serverStateAfterControl.Forward.x; //YAngDiff = clientDirection.y - serverStateAfterControl.Forward.y; //ZAngDiff = clientDirection.z - serverStateAfterControl.Forward.z; AngDiff = clientAngle - serverStateAfterControl.Angle; Debug.Log( "Diff: " + XDiff.ToString() + ", " + YDiff.ToString() + ", " + ZDiff.ToString() + ", " + AngDiff.ToString() ); #endregion 11C #region 11D: If the player is out of tolerance, then send a correction if (Mathf.Abs(XDiff) > PosTolerance || Mathf.Abs(YDiff) > PosTolerance || Mathf.Abs(ZDiff) > PosTolerance || Mathf.Abs(AngDiff) > DirTolerance) //Mathf.Abs(XAngDiff) > DirTolerance || //Mathf.Abs(YAngDiff) > DirTolerance || //Mathf.Abs(ZAngDiff) > DirTolerance) { Debug.Log("Sending correction..."); player.LastCorrectionSent = lastControlApplied; // Send the current position // If we send the correction to the old position, it forces the client to apply more contorl commands on its own, creating a larger margin of error SceneCharacter3D scenechar = (SceneCharacter3D)player.InGameCharacter; GetComponent <NetworkView>().RPC("CorrectPosition", info.sender, player.LastControlNumApplied, player.InGameCharacter.state.pos, scenechar.state.momentum, player.InGameCharacter.state.angle, scenechar.state.velocity, scenechar.crouch_factor); } #endregion 11D }
void attach_cam_to_walker(SceneCharacter3D walker) { cam.transform.position = walker.head.transform.position; cam.transform.rotation = walker.head.transform.rotation; var angles = cam.transform.eulerAngles; angles.z -= 90; cam.transform.eulerAngles = angles; cam.transform.Translate(-.007f, 0, 0.07f); cam.transform.SetParent(walker.head.transform); }
// Use this for initialization void Start() { walker_char = walker.GetComponent <SceneCharacter3D>(); // Cursor.visible = false; Cursor.lockState = CursorLockMode.Locked; //Game.recolor_walker(walker, new Color(.7f, 0f, .3f)); Color c = new Color(0f, 1.0f, 0f); Mesh m = floor.GetComponent <MeshFilter>().sharedMesh; var colors = from n in Enumerable.Range(0, m.vertices.Length) select c; m.colors = colors.ToArray(); }
void attach_cam_to_walker(SceneCharacter3D walker) { cam.transform.position = walker.head.transform.position; cam.transform.rotation = walker.head.transform.rotation; var angles = cam.transform.eulerAngles; angles.z -= 90; cam.transform.eulerAngles = angles; var pos = cam.transform.position; pos += walker.state.forward_vector * .3f; cam.transform.position = pos; cam.transform.SetParent(walker.head.transform); }
public void RequestProjectile(NetworkMessageInfo info) { if (!IsActive) { return; } var attacker_player = Players[info.sender.guid]; Character attacker = attacker_player.BaseCharacter; SceneCharacter3D scene_attacker = SceneCharacters[attacker.Id]; if (scene_attacker.can_fire_plasma()) { InstantiatePlasma(scene_attacker); GetComponent <NetworkView>().RPC("ReceiveProjectile", RPCMode.Others, attacker.Id); } }
public static Grenade Fire(SceneCharacter3D c, GameObject fab) { var pos = c.head.transform.position; pos += c.head.transform.forward * .7f; pos -= c.head.transform.right * .25f; var rot = c.head.transform.rotation.eulerAngles; var quat = Quaternion.Euler(rot.x, rot.y, 0); var go = (GameObject)GameObject.Instantiate(fab, pos, quat); var grenade = go.GetComponent <Grenade>(); var t = go.transform; grenade.attack_time = Time.time; grenade.speed = -1 * c.move; grenade.speed += ((t.forward * 2) + t.up); grenade.fired_by = c.BaseCharacter.Id; return(grenade); }
// Use this for initialization void Start() { walker_char = walker.GetComponent <SceneCharacter3D>(); // Cursor.visible = false; Cursor.lockState = CursorLockMode.Locked; walker_char.recolor_walker(new Color(.7f, 0f, .3f)); walker_char.BaseCharacter.Id = 1000; //Color c = new Color(.2f, .2f, .2f); //Mesh m = floor.GetComponent<MeshFilter>().sharedMesh; //var colors = from n in Enumerable.Range(0, m.vertices.Length) select c; //m.colors = colors.ToArray(); ai3d = ai.GetComponent <AI3D>(); ai3d.Target = walker_char; ai3d.state.on_ground = true; Projectiles = new List <Projectile>(); switch_level("bwadi"); }
public static Plasma Fire(SceneCharacter3D c, GameObject fab) { int gun = 1; float energy = 0; if (c.plasma1 < c.plasma2) { if (c.plasma2 > c.min_plasma_power) { energy = c.plasma2; c.plasma2 = 0; gun = -1; } } else // c.plasma1 >= c.plasma2 { if (c.plasma1 > c.min_plasma_power) { energy = c.plasma1; c.plasma1 = 0; } } var pos = c.head.transform.position; pos += c.head.transform.forward * 1.3f; pos += c.head.transform.up * .40f * gun; pos += c.head.transform.right * -.3f; var rot = c.head.transform.rotation; var proj = (GameObject)GameObject.Instantiate(fab, pos, rot); var p = proj.GetComponent <Plasma>(); p.set_energy(energy); p.fired_by = c.BaseCharacter.Id; p.speed = proj.transform.forward * 2f; return(p); }
public void InstantiateGrenade(SceneCharacter3D character) { Projectiles.Add(Grenade.Fire(character, GrenadePrefab)); }
public void InstantiatePlasma(SceneCharacter3D character) { Projectiles.Add(Plasma.Fire(character, PlasmaPrefab)); }
/// <summary> /// Update is called once per frame /// </summary> void Update() { if (!IsActive) { return; } //Debug.Log("Level: " + Application.loadedLevelName + "\n MyCharacterx: " + MyCharacter); if (MyCharacter == null || Application.loadedLevelName == MainMenuScene) { return; } if (SceneInformation == null) { LoadSceneInfo(); GameLevel = new Level(); GameLevel.load(GameLevelFile); GameObject level_object = GameLevel.game_object(); level_object.transform.parent = SceneInformation.transform; } if (CharactersToInstantiate.Count > 0) { foreach (var character in CharactersToInstantiate) { InstantiateSceneCharacter(character); } CharactersToInstantiate.Clear(); } if (ProjectilesToInstantiate.Count > 0) { foreach (var proj in ProjectilesToInstantiate) { InstantiatePlasma(SceneCharacters[proj]); } ProjectilesToInstantiate.Clear(); } if (MyPlayer == null && SceneCharacters != null && SceneCharacters.ContainsKey(MyCharacter.Id)) { MyPlayer = SceneCharacters[MyCharacter.Id]; MyPlayer.Client = this; MyPlayer.BaseCharacter = MyCharacter; MyPlayer.tag = "Player"; MyPlayer.BaseCharacter.R = MyColor.r; MyPlayer.BaseCharacter.G = MyColor.g; MyPlayer.BaseCharacter.B = MyColor.b; //recolor_walker(MyPlayer.gameObject, MyColor); GetComponent <NetworkView>().RPC("ClientColor", RPCMode.Server, MyColor.r, MyColor.g, MyColor.b); } if (CurrentGameState != GameStates.LevelLoaded || MyPlayer == null) { return; } InterpolateCharacters(); UpdateControls(); MovePlayer(); UpdateCamera(); UpdateCombatControls(); ValidateMyPosition(); HandleProjectiles(); }
// 7D: Move each character closer toward its intended location public void InterpolateCharacters() { foreach (int charId in CharacterIntendedStates.Keys) { SceneCharacter3D character = SceneCharacters[charId]; float portionOfDiffToMove = Mathf.Min(Time.deltaTime / ROUND_LENGTH, 1f); // Interpolate toward the intended position Vector3 curentPosition = character.transform.position; Vector3 positionDiff = CharacterPositionDiffs[charId]; float newXPos = curentPosition.x + (positionDiff.x * portionOfDiffToMove); float newYPos = curentPosition.y + (positionDiff.y * portionOfDiffToMove); float newZPos = curentPosition.z + (positionDiff.z * portionOfDiffToMove); character.transform.position = new Vector3( newXPos, newYPos, newZPos ); // Interpolate toward the intended direction //Vector3 curentDirection = character.transform.forward; float directionDiff = CharacterDirectionDiffs[charId]; /*float newXDir = curentDirection.x + (directionDiff.x * portionOfDiffToMove); * float newYDir = curentDirection.y + (directionDiff.y * portionOfDiffToMove); * float newZDir = curentDirection.z + (directionDiff.z * portionOfDiffToMove); * Vector3 newDir = new Vector3( * newXDir, * newYDir, * newZDir * );*/ //character.transform.forward = newDir; //var local = character.transform.InverseTransformDirection(newDir); //var fwd = character.transform.TransformDirection(Vector3.forward); //character.state.angle = Vector3.Angle(local, Vector3.forward); //character.state.angle = newYDir; //var angle = character.transform.localEulerAngles.y + (directionDiff * portionOfDiffToMove); // var angle = character.transform.localEulerAngles.y; if (directionDiff > 10) { Debug.Log(directionDiff); } angle = angle + (directionDiff * portionOfDiffToMove); if (angle > 359) { angle -= 359f; } if (angle < 0) { angle = 359f - angle; } character.transform.localEulerAngles = new Vector3( 0, angle, 0); //character.state.angle = angle; Quaternion currentHeadRot = character.head.transform.localRotation; Quaternion headRotDiff = CharacterHeadRotDiffs[charId]; float newXHeadRot = currentHeadRot.x + (headRotDiff.x * portionOfDiffToMove); float newYHeadRot = currentHeadRot.y + (headRotDiff.y * portionOfDiffToMove); float newZHeadRot = currentHeadRot.z + (headRotDiff.z * portionOfDiffToMove); float newWHeadRot = currentHeadRot.w + (headRotDiff.w * portionOfDiffToMove); character.head.transform.localRotation = new Quaternion( newXHeadRot, newYHeadRot, newZHeadRot, newWHeadRot ); float currentCrouchFactor = character.crouch_factor; float crouchFactorDiff = CharacterCrouchFactorDiffs[charId]; float newCrouchFactor = currentCrouchFactor + (crouchFactorDiff * portionOfDiffToMove); character.state.velocity = CharacterIntendedStates[charId].Velocity; character.crouch_factor = newCrouchFactor; character.LegUpdate(CharacterIntendedStates[charId].Walking); var temp = character.head.transform.localPosition; temp.z = character.head_rest_y - newCrouchFactor * SceneCharacter3D.crouch_dist; character.head.transform.localPosition = temp; } }
public void UpdateCharacter(int charId, Vector3 position, float direction, int walking, Quaternion headRot, Vector3 velocity, float crouchfactor) { ////Debug.Log ("Update called for " + charId + " at " + position.x + ", " + position.y + ", " + position.z); // Don't update self if using client-side prediction if (CurrentGameState != Game.GameStates.LevelLoaded || MyPlayer == null || (ClientSidePrediction && charId.Equals(((Character)MyPlayer).Id)) || !SceneCharacters.ContainsKey(charId) ) { return; } SceneCharacter3D character = SceneCharacters[charId]; ObjectState charState = new ObjectState(charId, position, direction, headRot, velocity, crouchfactor, walking); // TODO: fix this to call a special method just updating the legs // character.GetComponent<SceneCharacter3D>().Move(1f, 0f, Time.deltaTime, false); if (!CharacterInterpolation) { character.transform.position = position; character.state.velocity = velocity; character.state.angle = direction; character.head.transform.localRotation = headRot; character.crouch_factor = crouchfactor; character.transform.localEulerAngles = new Vector3(0, direction, 0); return; } // 7A) Store the character state from the server if (CharacterIntendedStates.ContainsKey(charId)) { CharacterIntendedStates.Remove(charId); CharacterPositionDiffs.Remove(charId); CharacterDirectionDiffs.Remove(charId); CharacterHeadRotDiffs.Remove(charId); CharacterCrouchFactorDiffs.Remove(charId); } CharacterIntendedStates.Add(charId, charState); // 7B) Calculate the position difference Vector3 currentCharPosition = character.transform.position; Vector3 intendedCharacterPosition = charState.Position; CharacterPositionDiffs.Add(charId, new Vector3( intendedCharacterPosition.x - currentCharPosition.x, intendedCharacterPosition.y - currentCharPosition.y, intendedCharacterPosition.z - currentCharPosition.z )); // Calculate the direction difference float currentCharDirection = character.transform.localEulerAngles.y; float intendedCharacterDirection = charState.Angle; /*CharacterDirectionDiffs.Add(charId, new Vector3( * intendedCharacterDirection.x - currentCharDirection.x, * intendedCharacterDirection.y - currentCharDirection.y, * intendedCharacterDirection.z - currentCharDirection.z * )); */ // TODO: use Mathf.DeltaAngle instead and test //float phi = Mathf.Abs(currentCharDirection - intendedCharacterDirection) % 360f; //float dist = phi > 180 ? 360 - phi : phi; float dist = Mathf.DeltaAngle(currentCharDirection, intendedCharacterDirection); CharacterDirectionDiffs.Add(charId, dist); Quaternion currentCharHeadRot = character.head.transform.localRotation; Quaternion intendedCharacterHeadRot = charState.HeadRot; CharacterHeadRotDiffs.Add(charId, new Quaternion( intendedCharacterHeadRot.x - currentCharHeadRot.x, intendedCharacterHeadRot.y - currentCharHeadRot.y, intendedCharacterHeadRot.z - currentCharHeadRot.z, intendedCharacterHeadRot.w - currentCharHeadRot.w )); float currentCharCrouchFactor = character.crouch_factor; float intendedCharacterCrouchFactor = charState.CrouchFactor; CharacterCrouchFactorDiffs.Add(charId, intendedCharacterCrouchFactor - currentCharCrouchFactor); }
// 14: Server processes attack request public void RequestAttack(NetworkMessageInfo info) { if (!IsActive) { return; } AttackerMoved = false; //Debug.Log ("Client is requesting an attack"); var attackingPlayer = Players[info.sender.guid]; Character attacker = attackingPlayer.BaseCharacter; SceneCharacter3D sceneAttacker = SceneCharacters[attacker.Id]; // 14A: Server checks attack validation if (!attacker.IsAlive) { return; } // 14B: Server sends attack message to all clients GetComponent <NetworkView>().RPC("ReceiveCharacterAttacks", RPCMode.Others, attacker.Id); // 16: Server calculates attack results #region Determine Hit var roundWhenPlayerAttacked = Rounds[attackingPlayer.RoundLastRespondedTo]; // 16A: Server rewinds the attacker to its position when the client attacked #region Rewind Attacker State var presentAttackerState = new ObjectState(0, sceneAttacker.transform.position, sceneAttacker.state.angle, Quaternion.identity, sceneAttacker.state.velocity, sceneAttacker.crouch_factor, sceneAttacker.walking ); if (LatencyCompensation) { Debug.Log("Rewinding attacker"); var oldAttackerState = roundWhenPlayerAttacked.CurrentObjectStates[attacker.Id]; sceneAttacker.transform.position = oldAttackerState.Position; sceneAttacker.state.angle = oldAttackerState.Angle; sceneAttacker.state.velocity = oldAttackerState.Velocity; sceneAttacker.crouch_factor = oldAttackerState.CrouchFactor; } #endregion Rewind Attacker State foreach (var potentialTarget in SceneCharacters.Values) { TargetMoved = false; // Check friendly fire if (!FriendlyFire && ((Character)potentialTarget).Team == attacker.Team) { continue; } // 16B: Server rewinds each potential target to its position when the client attacked #region Rewind Target State var presentTargetState = new ObjectState(0, potentialTarget.transform.position, potentialTarget.state.angle, Quaternion.identity, potentialTarget.state.velocity, potentialTarget.crouch_factor, potentialTarget.walking ); if (LatencyCompensation) { Debug.Log("Rewinding target"); var oldTargetState = roundWhenPlayerAttacked.CurrentObjectStates[((Character)potentialTarget).Id]; potentialTarget.transform.position = oldTargetState.Position; potentialTarget.state.angle = oldTargetState.Angle; potentialTarget.state.velocity = oldTargetState.Velocity; potentialTarget.crouch_factor = oldTargetState.CrouchFactor; } #endregion Rewind Target State // 16C: Server checks attack logic if (potentialTarget.transform.IsWithinArc(sceneAttacker.transform, attacker.ArmLength + 2f, 120f)) { CharacterHits(attacker, (Character)potentialTarget); // 16D-E } // 16F: Server returns each potential target to its current position #region Reset Target State if (LatencyCompensation && !TargetMoved) { Debug.Log("Unwinding target"); potentialTarget.transform.position = presentTargetState.Position; potentialTarget.state.angle = presentTargetState.Angle; potentialTarget.state.velocity = presentTargetState.Velocity; potentialTarget.crouch_factor = presentTargetState.CrouchFactor; } #endregion Reset Target State } #region Reset Attacker State // 16G: Server returns the attacker to the current position if (LatencyCompensation && !AttackerMoved) { Debug.Log("Unwinding attacker"); sceneAttacker.transform.position = presentAttackerState.Position; sceneAttacker.state.angle = presentAttackerState.Angle; sceneAttacker.state.velocity = presentAttackerState.Velocity; sceneAttacker.crouch_factor = presentAttackerState.CrouchFactor; } #endregion Reset Attacker State #endregion Determine Hit }