void DoInCup() { ThryBP_Glass cup = _mainScript.GetCup(state[1], state[2], state[3]); if (Utilities.IsValid(cup)) { //if ball is not in cup teleport ball in cup Collider c = cup.colliderForThrow; c.enabled = true; Vector3 cPoint = c.ClosestPoint(transform.position); c.enabled = false; Bounds b = cup.GetBounds(); b.size = b.size += Vector3.up; if (Vector3.Distance(cPoint, transform.position) > 0.01f && ((_rigidbody.velocity.sqrMagnitude == 0) || (b.Contains(transform.position) == false))) { //Debug.Log($"cPoint: {cPoint.ToString("F3")} point: {transform.position.ToString("F3")}"); //Debug.Log($"[ThryBP] Teleported ball into cup ({state[1]},{state[2]},{state[3]})"); transform.position = cup.GetBounds().center; } else if (Networking.IsOwner(gameObject)) { if (_mainScript.gamemode == 0) { if (Time.time - stateStartTime > (autoRespawnBallAfterCupHit ? 2 : 20)) { _mainScript.CountCupHit(state[1], state[2], state[3], currentPlayer, state[0] == STATE_RIMING ? 1 : 0); _mainScript.RemoveCup(state[1], state[2], state[3], currentPlayer); Respawn(); } } else if (_mainScript.gamemode == 1) { if (Time.time - stateStartTime > 1) { _mainScript.CountCupHit(state[1], state[2], state[3], currentPlayer, state[0] == STATE_RIMING ? 1 : 0); _mainScript.RemoveCup(state[1], state[2], state[3], currentPlayer); Respawn(); } } else if (_mainScript.gamemode == 2) { if (Time.time - stateStartTime > 3) { _mainScript.CountCupHit(state[1], state[2], state[3], currentPlayer, state[0] == STATE_RIMING ? 1 : 0); Respawn(); } } } } }
private Vector3 OptimalVectorChangeAngle(Vector3 velocity, Vector3 position, float tableHeight, ThryBP_Glass aimedCup) { //Calculate trajectory to that cup Vector3 horizonzalDistance = aimedCup.transform.position - position; horizonzalDistance.y = 0; //https://www.youtube.com/watch?v=bqYtNrhdDAY&ab_channel=MichelvanBiezen //https://www.youtube.com/watch?v=pQ23Eb-bXvQ&ab_channel=MichelvanBiezen float g = -Physics.gravity.y; float v2 = velocity.sqrMagnitude; float x = horizonzalDistance.magnitude; float h = position.y - (tableHeight + aimedCup.GetBounds().size.y); float phi = Mathf.Atan(x / h); float theta = (Mathf.Acos(((g * x * x / v2) - h) / Mathf.Sqrt(h * h + x * x)) + phi) / 2; Vector3 newVel = (horizonzalDistance.normalized * Mathf.Cos(theta) + Vector3.up * Mathf.Sin(theta)) * velocity.magnitude; if (float.IsNaN(theta)) { //cant reacht cup with current velocity //just aim in it's direction instead Vector3 horizontalVel = velocity; horizontalVel.y = 0; newVel = horizonzalDistance.normalized * horizontalVel.magnitude; newVel.y = velocity.y; } return(newVel); }
private Vector3 OptimalVectorChangeStrength(Vector3 velocity, Vector3 position, ThryBP_Glass cup) { Vector3 cupOpening = cup.transform.position + Vector3.up * cup.GetBounds().size.y; Vector3 horizonzalVector = cupOpening - position; horizonzalVector.y = 0; Vector3 horizonzalVelocity = velocity; horizonzalVelocity.y = 0; //https://www.youtube.com/watch?v=mOYJKv22qeQ&list=PLX2gX-ftPVXUUlf-9Eo_6ut4kP6wKaSWh&index=7&ab_channel=MichelvanBiezen // d = v0 * cos(w) * t // => t = d / (v0 * cos(w)) // y = y0 + v0 * sin(w) * t - 0.5 * g * t2 // y = y0 + v0 * sin(w) * ( d / (v0 * cos(w)) ) - 0.5 * g * ( d / (v0 * cos(w)) )2 // y = y0 + tan(w) * d - 0.5 * g * ( d / (v0 * cos(w)) )2 // y0 - y + tan(w) * d = 0.5 * g * ( d / (v0 * cos(w)) )2 // 2(y0 - y + tan(w) * d) / g = ( d / (v0 * cos(w)) )2 // sqrt( 2(y0 - y + tan(w) * d) / g) = d / (v0 * cos(w)) // v0 * cos(w) = d / sqrt( 2(y0 - y + tan(w) * d) / g) // v0 = d / sqrt( 2(y0 - y + tan(w) * d) / g) / cos(w) float d = horizonzalVector.magnitude; float y0 = position.y; float y = cupOpening.y; float w = Mathf.Deg2Rad * Vector3.Angle(horizonzalVelocity, velocity); float g = -Physics.gravity.y; float v0 = d / Mathf.Sqrt(2 * (y0 - y + Mathf.Tan(w) * d) / g) / Mathf.Cos(w); Vector3 newDirection = horizonzalVector.normalized * horizonzalVelocity.magnitude; newDirection.y = velocity.y; return(newDirection.normalized * v0); }
private Vector3 DoAIVectoring(Vector3 velocity, Vector3 position, float skill) { if (skill == 0) { return(velocity); } //Get Point where ball will hit table Vector3 predictionTableHit = PredictTableHit(velocity, position, tableHeight); ThryBP_Glass cup = GetClosestGlassToPredictedTableCollision(predictionTableHit); if (cup == null) { return(velocity); } Vector3 cupOpening = cup.transform.position + Vector3.up * cup.GetBounds().size.y; Vector3 optimalVector = OptimalVectorChangeStrength(velocity, position, cup); float lerping = Random.Range(0f, 1f); if (lerping < skill) { lerping = 1; } velocity = Vector3.Lerp(velocity, optimalVector, lerping); return(velocity); }
void DoRimming() { if (rimming < RIMMING_TOTAL_AGULAR_ROTATION) { ThryBP_Glass cup = _mainScript.GetCup(state[1], state[2], state[3]); if (Utilities.IsValid(cup)) { rimming += RIMMING_SPEED * Time.deltaTime; float inside = 0.9f - rimming / RIMMING_TOTAL_AGULAR_ROTATION * 0.15f; float downwards = 1 - rimming / RIMMING_TOTAL_AGULAR_ROTATION * 0.3f; float angle = (rimming - Mathf.Pow(rimming * 0.009f, 2)) / cup.circumfrence * 0.4f; transform.position = cup.transform.position + Vector3.up * (cup.GetBounds().size.y *downwards) + Quaternion.Euler(0, angle, 0) * Vector3.forward * (cup.radius * cup.transform.lossyScale.x * inside - _radius); } } else { ThryBP_Glass cup = _mainScript.GetCup(state[1], state[2], state[3]); if (Utilities.IsValid(cup)) { cup.colliderInside.SetActive(true); cup.colliderForThrow.enabled = false; _rigidbody.velocity = Quaternion.Euler(0, 90 + rimming, 0) * Vector3.forward * 0.3f; //in circle _rigidbody.velocity += Quaternion.Euler(0, rimming + 180, 0) * Vector3.forward * 0.1f; //inwards _rigidbody.velocity += Vector3.down * 0.1f; //downwards SetDynamic(); localState = STATE_IN_CUP; stateStartTime = Time.time; _TriggerSplash(); _pickup.pickupable = !autoRespawnBallAfterCupHit; } } }
private void BallGlassCollision(Collision collision, ThryBP_Glass hitGlass) { Bounds b = hitGlass.GetBounds(); bool isCollisionOnTop = (b.max.y < transform.position.y); SetDynamic(); if (isCollisionOnTop) { Vector3 p1 = transform.position; p1.y = 0; Vector3 p2 = hitGlass.transform.position; p2.y = 0; float distanceFromCenter = Vector3.Distance(p1, p2) / ((b.extents.x + b.extents.z) / 2); if (distanceFromCenter < COLLISION_MAXIMUM_DISTANCE_FROM_CENTER) { float angle = Vector3.Angle(_lastvelocies[_lastvelociesHead], Vector3.down); //bool tripOnEdge = distanceFromCenter > Random.Range(0, 0.85f); bool tripOnEdge = distanceFromCenter > Random.Range(0.4f, 0.7f) && angle > Random.Range(45, 80); //if it lands really flat chances are higher for it to ride edge if (tripOnEdge) { SetState(STATE_RIMING); state[1] = (byte)hitGlass.player.playerIndex; state[2] = (byte)hitGlass.row; state[3] = (byte)hitGlass.collum; rimming = Vector3.Angle(hitGlass.transform.rotation * Vector3.forward, p2 - p1); if ((p2 - p1).x > 0) { rimming = 360 - rimming; } rimming = rimming % 360; state[4] = (byte)(rimming / 2); state[5] = (byte)(distanceFromCenter * 100); } else { hitGlass.colliderForThrow.enabled = false; hitGlass.colliderInside.SetActive(true); _pickup.pickupable = !autoRespawnBallAfterCupHit; SetState(STATE_IN_CUP); state[1] = (byte)hitGlass.player.playerIndex; state[2] = (byte)hitGlass.row; state[3] = (byte)hitGlass.collum; _TriggerSplash(); _rigidbody.velocity = Vector3.down * startVelocityLocal.magnitude; } RequestSerialization(); } } }
private Vector3 DoAimbotVectoring(Vector3 velocity, Vector3 position, float strength) { if (strength == 0) { return(velocity); } //Get Point where ball will hit table Vector3 predictionTableHit = PredictTableHit(velocity, position, tableHeight); ThryBP_Glass cup = GetClosestGlassToPredictedTableCollision(predictionTableHit); if (cup == null) { return(velocity); } Vector3 cupOpening = cup.transform.position + Vector3.up * cup.GetBounds().size.y; Vector3 hitOnCupPlane = PredictTableHit(velocity, position, cupOpening.y); if (Vector3.Distance(cupOpening, hitOnCupPlane) > strength) { return(velocity); } return(OptimalVectorChangeStrength(velocity, position, cup)); }
public float GetHeight() { return(glass.GetBounds().size.y); }