added "finish" button to dialogue UI, implementation of many, many trinket's effects, autot-argetting fix on death, added script for particles/player following
This commit is contained in:
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using Invector.vCharacterController.AI.FSMBehaviour;
|
||||
using Beyond;
|
||||
using System;
|
||||
using Invector; // Required for vDamage
|
||||
|
||||
namespace Beyond
|
||||
{
|
||||
@@ -70,14 +71,23 @@ namespace Beyond
|
||||
_playerController = Player.Instance.GetComponent<bThirdPersonController>();
|
||||
if (_playerController == null)
|
||||
{
|
||||
Debug.LogError("AutoTargetting: Could not find bThirdPersonController on Player.Instance! Custom roll rotation may not work correctly.");
|
||||
Debug.LogError("AutoTargetting: Could not find bThirdPersonController on Player.Instance!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Subscribe to Player Death
|
||||
_playerController.onDead.AddListener(OnPlayerDead);
|
||||
}
|
||||
|
||||
_gameStateManager = GameStateManager.Instance;
|
||||
if (_gameStateManager != null)
|
||||
{
|
||||
_gameStateManager.m_OnStateChanged.AddListener(HandleGameStateChanged);
|
||||
HandleGameStateChanged(_gameStateManager.CurrentState);
|
||||
// Initial check, but avoid running if dead
|
||||
if(_playerController != null && _playerController.currentHealth > 0)
|
||||
{
|
||||
HandleGameStateChanged(_gameStateManager.CurrentState);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -88,11 +98,6 @@ namespace Beyond
|
||||
if (targetLockSystem == null)
|
||||
{
|
||||
targetLockSystem = Player.Instance.GetComponentInChildren<bLockOn>(true);
|
||||
if (targetLockSystem == null)
|
||||
{
|
||||
Debug.LogWarning("AutoTargetting: bLockOn system not found. Auto-lock will be disabled.");
|
||||
autoLockSelectedTarget = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetLockSystem != null)
|
||||
@@ -106,8 +111,13 @@ namespace Beyond
|
||||
{
|
||||
if (_gameStateManager != null) _gameStateManager.m_OnStateChanged.RemoveListener(HandleGameStateChanged);
|
||||
|
||||
StopAndClearAllFadeCoroutines();
|
||||
// Unsubscribe from Player Death
|
||||
if (_playerController != null)
|
||||
{
|
||||
_playerController.onDead.RemoveListener(OnPlayerDead);
|
||||
}
|
||||
|
||||
StopAndClearAllFadeCoroutines();
|
||||
if (_targetingLoopCoroutine != null) StopCoroutine(_targetingLoopCoroutine);
|
||||
|
||||
if (targetLockSystem != null)
|
||||
@@ -120,6 +130,36 @@ namespace Beyond
|
||||
#endregion
|
||||
|
||||
#region Core Logic
|
||||
|
||||
private void OnPlayerDead(GameObject deadObject)
|
||||
{
|
||||
// Immediately clear targets and stop the loop when player dies
|
||||
ClearTarget(false);
|
||||
|
||||
if (_targetingLoopCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_targetingLoopCoroutine);
|
||||
_targetingLoopCoroutine = null;
|
||||
}
|
||||
|
||||
if (targetLockSystem != null)
|
||||
{
|
||||
targetLockSystem.SetLockOn(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetSystem()
|
||||
{
|
||||
ClearTarget(false);
|
||||
_manualSwitchCooldownActive = false;
|
||||
_manualSwitchCooldownTimer = 0f;
|
||||
|
||||
// Restart the loop if we are in combat
|
||||
if (_gameStateManager != null && _gameStateManager.CurrentState == GameStateManager.State.COMBAT)
|
||||
{
|
||||
if (_targetingLoopCoroutine == null) _targetingLoopCoroutine = StartCoroutine(TargetingLoop());
|
||||
}
|
||||
}
|
||||
|
||||
private void StopAndClearAllFadeCoroutines()
|
||||
{
|
||||
@@ -135,6 +175,9 @@ namespace Beyond
|
||||
|
||||
private void HandleGameStateChanged(GameStateManager.State newState)
|
||||
{
|
||||
// Don't start loops if player is dead
|
||||
if (_playerController != null && _playerController.currentHealth <= 0) return;
|
||||
|
||||
if (newState == GameStateManager.State.COMBAT)
|
||||
{
|
||||
if (_targetingLoopCoroutine == null) _targetingLoopCoroutine = StartCoroutine(TargetingLoop());
|
||||
@@ -155,6 +198,11 @@ namespace Beyond
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (_playerController != null && _playerController.currentHealth <= 0)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (_manualSwitchCooldownActive)
|
||||
{
|
||||
_manualSwitchCooldownTimer -= targetingInterval;
|
||||
@@ -174,7 +222,6 @@ namespace Beyond
|
||||
{
|
||||
if (_playerTransform == null || _gameStateManager == null || _manualSwitchCooldownActive) return;
|
||||
|
||||
// Step 1: Always find the absolute best candidate in range right now.
|
||||
vFSMBehaviourController bestCandidate = null;
|
||||
float minDistanceSqr = maxTargetingDistance * maxTargetingDistance;
|
||||
HashSet<vFSMBehaviourController> combatControllers = _gameStateManager.GetActiveCombatcontrollers();
|
||||
@@ -195,13 +242,11 @@ namespace Beyond
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: If the best candidate is different from our current one, switch the highlight.
|
||||
if (CurrentTarget != bestCandidate)
|
||||
{
|
||||
SetNewTarget(bestCandidate);
|
||||
}
|
||||
|
||||
// Step 3: Every update, evaluate and apply the correct lock-on state for the current target.
|
||||
UpdateLockOnState();
|
||||
}
|
||||
|
||||
@@ -209,7 +254,6 @@ namespace Beyond
|
||||
{
|
||||
if (targetLockSystem == null || _playerTransform == null) return;
|
||||
|
||||
// Determine if the target *should* be locked based on distance rules.
|
||||
bool shouldBeLocked = false;
|
||||
if (CurrentTarget != null && (autoLockSelectedTarget || alwaysLockOnInCombat))
|
||||
{
|
||||
@@ -217,21 +261,15 @@ namespace Beyond
|
||||
|
||||
if (targetLockSystem.isLockingOn)
|
||||
{
|
||||
// If already locked, stay locked unless we are beyond the unlock threshold.
|
||||
shouldBeLocked = distanceToTarget <= unlockDistanceThreshold;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If not locked, we only engage the lock if we are within the auto-lock distance.
|
||||
shouldBeLocked = distanceToTarget <= autoLockOnDistance;
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronize the desired state with the lock-on system.
|
||||
Transform desiredLockTarget = shouldBeLocked ? CurrentTarget.transform : null;
|
||||
|
||||
// --- THIS IS THE FIX ---
|
||||
// We now pass the 'shouldBeLocked' boolean to tell the system whether to lock or unlock.
|
||||
targetLockSystem.ManuallySetLockOnTarget(desiredLockTarget, shouldBeLocked);
|
||||
|
||||
if (alwaysLockOnInCombat && desiredLockTarget != null && !targetLockSystem.isLockingOn)
|
||||
@@ -261,11 +299,7 @@ namespace Beyond
|
||||
|
||||
public void ExecuteRotationTowardsCurrentTarget(float deltaTime)
|
||||
{
|
||||
if (_playerController != null && !_playerController.enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_playerController != null && !_playerController.enabled) return;
|
||||
if (CurrentTarget == null || _playerTransform == null) return;
|
||||
|
||||
Vector3 directionToTarget = CurrentTarget.transform.position - _playerTransform.position;
|
||||
@@ -311,6 +345,16 @@ namespace Beyond
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
// --- Restored Method ---
|
||||
public float GetCurrentTargetHealth()
|
||||
{
|
||||
if (CurrentTarget != null && CurrentTarget.aiController != null)
|
||||
{
|
||||
return CurrentTarget.aiController.currentHealth;
|
||||
}
|
||||
return -1f;
|
||||
}
|
||||
|
||||
public bool IsTargetInAngle(Transform sourceTransform, vFSMBehaviourController targetAI, float angleThreshold)
|
||||
{
|
||||
if (targetAI == null || sourceTransform == null) return false;
|
||||
@@ -329,15 +373,6 @@ namespace Beyond
|
||||
return distSqr <= (maxTargetingDistance * maxTargetingDistance);
|
||||
}
|
||||
|
||||
public float GetCurrentTargetHealth()
|
||||
{
|
||||
if (CurrentTarget != null && CurrentTarget.aiController != null)
|
||||
{
|
||||
return CurrentTarget.aiController.currentHealth;
|
||||
}
|
||||
return -1f;
|
||||
}
|
||||
|
||||
public void ClearTarget(bool findNewOneImmediately)
|
||||
{
|
||||
if (targetLockSystem != null)
|
||||
@@ -349,7 +384,7 @@ namespace Beyond
|
||||
|
||||
if (findNewOneImmediately && _gameStateManager != null && _gameStateManager.CurrentState == GameStateManager.State.COMBAT)
|
||||
{
|
||||
if (!_manualSwitchCooldownActive)
|
||||
if (_playerController != null && _playerController.currentHealth > 0 && !_manualSwitchCooldownActive)
|
||||
{
|
||||
UpdateTarget();
|
||||
}
|
||||
@@ -359,7 +394,6 @@ namespace Beyond
|
||||
#endregion
|
||||
|
||||
#region Visuals
|
||||
|
||||
private Renderer[] GetTargetRenderers(vFSMBehaviourController targetController)
|
||||
{
|
||||
if (targetController == null) return new Renderer[0];
|
||||
@@ -399,7 +433,6 @@ namespace Beyond
|
||||
}
|
||||
if (material != null) material.SetColor(materialHighlightPropertyName, toValue);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,7 @@ namespace Beyond
|
||||
public bMeleeCombatInput MeleeCombatInput => m_meleeCombatInput;
|
||||
|
||||
// --- TRINKET SYSTEM INTEGRATION START ---
|
||||
// Initialize default values to 1f to prevent divide-by-zero or zero-stat issues on startup
|
||||
private TrinketManager.TrinketStats m_trinketStats = new TrinketManager.TrinketStats
|
||||
{
|
||||
healthMult = 1f,
|
||||
@@ -85,7 +86,8 @@ namespace Beyond
|
||||
faithRegenMult = 1f,
|
||||
attackSpeedMult = 1f,
|
||||
thornDamageMult = 1f,
|
||||
staminaMult = 1f
|
||||
staminaMult = 1f,
|
||||
soulfireDamageMult = 1f
|
||||
};
|
||||
|
||||
public TrinketManager.TrinketStats CurrentTrinketStats => m_trinketStats;
|
||||
@@ -93,29 +95,66 @@ namespace Beyond
|
||||
public void UpdateTrinketStats(TrinketManager.TrinketStats newStats)
|
||||
{
|
||||
m_trinketStats = newStats;
|
||||
// Force stats recalculation
|
||||
UpdatePlayerStatistics();
|
||||
|
||||
// 1. Recalculate Base Stats (Health/Faith/Stamina/Natural Regen)
|
||||
// This sets m_vController.healthRecovery to the base natural value (from Maturity/Brightness)
|
||||
UpdatePlayerStatistics();
|
||||
|
||||
// Apply immediate effects
|
||||
if (m_vController)
|
||||
// 2. Apply Speed & Animation Speed
|
||||
if (m_vController)
|
||||
{
|
||||
m_vController.speedMultiplier = m_trinketStats.speedMult;
|
||||
// 2. Apply Attack Speed (UI Method)
|
||||
|
||||
if (m_vController.animator)
|
||||
m_vController.animator.SetFloat("AttackSpeed", m_trinketStats.attackSpeedMult);
|
||||
|
||||
// --- HEALTH REGEN LOGIC START ---
|
||||
// Start with the base natural rate we just calculated in UpdatePlayerStatistics
|
||||
float totalRegenRate = m_vController.healthRecovery;
|
||||
float totalRegenCap = 1f; // Default 100% cap
|
||||
|
||||
// Add Passive Trinket Regen (e.g. "Growth" effect: Regen up to 50%)
|
||||
if (m_trinketStats.effectGrowth)
|
||||
{
|
||||
// Example: +2 HP/sec up to 50%
|
||||
totalRegenRate += 2f;
|
||||
totalRegenCap = 0.5f;
|
||||
}
|
||||
|
||||
// If you cast to bThirdPersonController, you can set the Cap
|
||||
if (m_vController is bThirdPersonController bController)
|
||||
{
|
||||
bController.healthRecoveryCap = totalRegenCap;
|
||||
}
|
||||
|
||||
// Update the final rate on the controller
|
||||
m_vController.SetHealthRecovery(totalRegenRate);
|
||||
// --- HEALTH REGEN LOGIC END ---
|
||||
}
|
||||
|
||||
// 3. Apply Damage Multiplier (NEW)
|
||||
// 3. Apply Damage Multipliers
|
||||
if (m_meleeManager)
|
||||
{
|
||||
// Calculate the base multiplier from stats
|
||||
// Start with the base multiplier from items
|
||||
float totalDamageMult = m_trinketStats.damageMult;
|
||||
totalDamageMult += 0.10f;
|
||||
|
||||
// Send to Melee Manager
|
||||
// "The Darkening": Bonus dmg
|
||||
if (m_trinketStats.effectDarkening)
|
||||
{
|
||||
totalDamageMult += 0.10f;
|
||||
}
|
||||
|
||||
// "Determination": Combo finish +5% damage
|
||||
// (Global application for now)
|
||||
if (m_trinketStats.effectDetermination)
|
||||
{
|
||||
totalDamageMult += 0.05f;
|
||||
}
|
||||
|
||||
// Send final value to your modified vMeleeManager
|
||||
// NOTE: Requires the SetGlobalDamageMultiplier method added to vMeleeManager
|
||||
m_meleeManager.SetGlobalDamageMultiplier(totalDamageMult);
|
||||
}
|
||||
|
||||
}
|
||||
// --- TRINKET SYSTEM INTEGRATION END ---
|
||||
|
||||
@@ -172,6 +211,7 @@ namespace Beyond
|
||||
private float faithBaseMaxValue = 100f;
|
||||
|
||||
private System.Action onMenuScrollClosed;
|
||||
// Updated Action signature to pass 3 floats for UI (Health, Faith, Stamina)
|
||||
public System.Action<float, float, float> onStatsUpdated;
|
||||
private UnityAction<Transform> onDialogueEnded;
|
||||
private bLockOn m_lockOn;
|
||||
@@ -231,28 +271,26 @@ namespace Beyond
|
||||
|
||||
private void OnDamageHit(vHitInfo arg0)
|
||||
{
|
||||
// Slow motion logic (existing)
|
||||
// Slow motion logic
|
||||
if (slowMoOnHtScale < 1f - float.Epsilon)
|
||||
{
|
||||
TimeController.Instance.Reset();
|
||||
}
|
||||
|
||||
// 1. Health Vampirism
|
||||
// 1. Health Vampirism (Vitality)
|
||||
if (m_trinketStats.effectHealthVampirism)
|
||||
{
|
||||
// Logic: Heal 2% of Player's Max Health per hit
|
||||
// Mathf.Max ensures we always heal at least 1 HP
|
||||
// Heal 2% of Max Health per hit, min 1 HP
|
||||
int healAmount = Mathf.Max(1, (int)(MaxHealth * 0.02f));
|
||||
m_vController.ChangeHealth(healAmount);
|
||||
}
|
||||
|
||||
// 2. Faith Vampirism
|
||||
// 2. Faith Vampirism (Trust)
|
||||
if (m_trinketStats.effectFaithVampirism)
|
||||
{
|
||||
// Logic: Add 1 Faith point per hit
|
||||
// Add 1 Faith point per hit
|
||||
UpdateFaithCurrentValue(1);
|
||||
}
|
||||
// ----------------------------
|
||||
}
|
||||
|
||||
private void OnConversationStarted(Transform transform)
|
||||
@@ -311,7 +349,7 @@ namespace Beyond
|
||||
controller.RemoveAnimatorTags();
|
||||
}
|
||||
|
||||
// ... [Audio Play Methods - kept same] ...
|
||||
// ... [Audio Play Methods] ...
|
||||
public void PlayNoFaithClip() { PlayRandomSound(m_noFaithClips); }
|
||||
private void PlayRandomSound(AudioClip[] sounds)
|
||||
{
|
||||
@@ -367,14 +405,32 @@ namespace Beyond
|
||||
public void OnReceivedDamage(vDamage damage)
|
||||
{
|
||||
if (m_cutScenePlaying) return;
|
||||
|
||||
// --- TRINKET DEFENSE CALCULATION ---
|
||||
// defenseMult of 0.9 means 90% damage taken (10% reduction)
|
||||
|
||||
// --- 1. DEFENSE CALCULATION ---
|
||||
// Example: 0.9 defenseMult = 90% damage taken (10% reduction)
|
||||
if (Mathf.Abs(m_trinketStats.defenseMult - 1f) > float.Epsilon)
|
||||
{
|
||||
damage.damageValue = (int)(damage.damageValue * m_trinketStats.defenseMult);
|
||||
}
|
||||
// -----------------------------------
|
||||
|
||||
// --- 2. THORN DAMAGE (Reflect Damage) ---
|
||||
if (m_trinketStats.thornDamageMult > 1f && damage.sender != null)
|
||||
{
|
||||
// Calculate reflect amount (Base damage * (Mult - 1))
|
||||
int thornVal = (int)(damage.damageValue * (m_trinketStats.thornDamageMult - 1f));
|
||||
|
||||
if (thornVal > 0)
|
||||
{
|
||||
vDamage reflectDmg = new vDamage(thornVal);
|
||||
reflectDmg.sender = transform;
|
||||
reflectDmg.damageType = "Thorns";
|
||||
reflectDmg.reaction_id = -1; // No flinch
|
||||
|
||||
// Uses Invector extension method to apply damage to sender
|
||||
damage.sender.gameObject.ApplyDamage(reflectDmg);
|
||||
}
|
||||
}
|
||||
// ----------------------------------------
|
||||
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
HapticEngine.ImpactFeedbackHeavy();
|
||||
@@ -396,6 +452,8 @@ namespace Beyond
|
||||
if (m_Respawner) m_Respawner.SaveRespawnPoint();
|
||||
}
|
||||
|
||||
// ... [Quest and Attribute Methods] ...
|
||||
|
||||
public List<Quest> GetAllGuilts()
|
||||
{
|
||||
if (!m_questJournal)
|
||||
@@ -525,12 +583,14 @@ namespace Beyond
|
||||
// --- TRINKET INTEGRATION IN STATS CALCULATION ---
|
||||
|
||||
// 1. Calculate specific total multipliers for UI scaling
|
||||
// 1. Calculate specific total multipliers
|
||||
float totalHealthMult = finalMultiplier * m_trinketStats.healthMult;
|
||||
float totalFaithMult = finalMultiplier * m_trinketStats.faithMult;
|
||||
float totalStaminaMult = finalMultiplier * (m_trinketStats.staminaMult > 0 ? m_trinketStats.staminaMult : 1f); // Handle 0 default
|
||||
// Handle 0 default for Stamina
|
||||
float validStaminaMult = m_trinketStats.staminaMult > 0 ? m_trinketStats.staminaMult : 1f;
|
||||
float totalStaminaMult = finalMultiplier * validStaminaMult;
|
||||
|
||||
// 2. Capture Current Health Percentage BEFORE changes
|
||||
// This prevents the health bar from looking empty when Max HP increases
|
||||
float healthPercent = m_vController.maxHealth > 0 ? m_vController.currentHealth / m_vController.maxHealth : 1f;
|
||||
|
||||
// 3. Apply Stats
|
||||
@@ -544,12 +604,16 @@ namespace Beyond
|
||||
m_vController.maxHealth = newMaxHealth;
|
||||
|
||||
// Apply Proportional Current Health
|
||||
// We update the current health to match the previous percentage
|
||||
//m_vController.currentHealth = Mathf.RoundToInt(newMaxHealth * healthPercent);
|
||||
// Uses ChangeHealth() because currentHealth has a protected setter
|
||||
m_vController.ChangeHealth(Mathf.RoundToInt(newMaxHealth * healthPercent));
|
||||
|
||||
// Stamina
|
||||
m_vController.maxStamina = Mathf.Round(totalStaminaMult * staminaBaseMaxValue);
|
||||
m_vController.staminaRecovery = (finalMultiplier * staminaBaseRegenValue);
|
||||
|
||||
// Natural Health Recovery (From Maturity/Brightness)
|
||||
// We set the BASE here. UpdateTrinketStats will later add any trinket bonuses to this value.
|
||||
m_vController.healthRecovery = finalMultiplier * healthBaseRegenValue;
|
||||
|
||||
// ------------------------------------------------
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -61,7 +61,8 @@ namespace Beyond
|
||||
[Description("Attack Speed Bonus")] AttackSpeedBonusPercent = 26,
|
||||
[Description("Faith Regen Bonus")] FaithRegenBonusPercent = 27,
|
||||
[Description("Thorn Damage Bonus")] ThornDamageBonusPercent = 28,
|
||||
[Description("Stamina Bonus")] StaminaBonusPercent = 29
|
||||
[Description("Stamina Bonus")] StaminaBonusPercent = 29,
|
||||
[Description("Soulfire Damage Bonus")] SoulfireDamageBonusPercent = 30
|
||||
}
|
||||
|
||||
public enum TrinketColor
|
||||
|
||||
@@ -13,6 +13,9 @@ namespace Beyond
|
||||
protected bool m_GodMode = false;
|
||||
public bool m_ignoreTriggers = true;
|
||||
|
||||
[Header("Beyond Health Logic")]
|
||||
// Default cap is 1.0 (100% HP)
|
||||
public float healthRecoveryCap = 1f;
|
||||
[Header("Beyond's Custom Settings")]
|
||||
[Tooltip("When 'Use RootMotion' is checked, and this is true, the animation's root motion will control character rotation (for 8-way directional movement). If false, the script will rotate the character to face the input direction.")]
|
||||
public bool useAnimationBasedRotation = false;
|
||||
@@ -52,6 +55,18 @@ namespace Beyond
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool canRecoverHealth
|
||||
{
|
||||
get
|
||||
{
|
||||
// Calculate the actual HP limit based on the cap
|
||||
float limitHP = maxHealth * healthRecoveryCap;
|
||||
|
||||
// Add the check: currentHealth must be LESS than the Limit
|
||||
return base.canRecoverHealth && (_currentHealth < limitHP);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDashingOrRolling()
|
||||
{
|
||||
return m_isDashing || isRolling;
|
||||
|
||||
@@ -24,25 +24,30 @@ namespace Beyond
|
||||
public float faithMult;
|
||||
public float damageMult;
|
||||
public float speedMult;
|
||||
public float staminaMult;
|
||||
public float attackSpeedMult;
|
||||
public float faithRegenMult;
|
||||
public float thornDamageMult;
|
||||
|
||||
// --- NEW ATTRIBUTES ---
|
||||
public float staminaMult; // For Stamina UI Scaling
|
||||
public float soulfireDamageMult; // For Magic Damage (Fireball, etc)
|
||||
|
||||
// Harmony Flags (Effects from table)
|
||||
// Renamed to match Player.cs usage
|
||||
public bool effectBalance; // Balance (Flask bonus)
|
||||
public bool effectCalmness; // Calmness (Longer shield)
|
||||
public bool effectFaithVampirism; // Trust (Faith vampirism) - Was effectTrust
|
||||
public bool effectBreeze; // Breeze (Freezing blast cost)
|
||||
public bool effectFaithVampirism; // Trust (Faith vampirism)
|
||||
public bool effectBreeze; // Zora's Focus (Buff Covert Gaze Radius/Length)
|
||||
public bool effectDetermination; // Determination (Combo damage)
|
||||
public bool effectHealthVampirism; // Vitality (Health vampirism) - Was effectVitality
|
||||
public bool effectHealthVampirism; // Vitality (Health vampirism)
|
||||
public bool effectEagerness; // Eagerness (Dash cooldown)
|
||||
public bool effectBloom; // Bloom (Spell cost reduced)
|
||||
public bool effectGrowth; // Growth (Cast restores HP)
|
||||
public bool effectRose; // Rose (Thorn damage)
|
||||
public bool effectDarkening; // The Darkening (Bonus dmg)
|
||||
public bool effectEclipse; // Eclipse (Bonus all)
|
||||
|
||||
// --- NEW EFFECTS ---
|
||||
public bool effectAngelEye; // Angel Eye (Silent Peek Cost = 0)
|
||||
}
|
||||
|
||||
private void Start()
|
||||
@@ -79,7 +84,10 @@ namespace Beyond
|
||||
attackSpeedMult = 1f,
|
||||
faithRegenMult = 1f,
|
||||
thornDamageMult = 1f,
|
||||
staminaMult = 1f
|
||||
|
||||
// Initialize New Stats
|
||||
staminaMult = 1f,
|
||||
soulfireDamageMult = 1f
|
||||
};
|
||||
|
||||
// 2. Get Currently Equipped Items
|
||||
@@ -96,14 +104,17 @@ namespace Beyond
|
||||
foreach (var item in equippedItems)
|
||||
{
|
||||
stats.healthMult += GetPct(item, bItemAttributes.HealthBonusPercent);
|
||||
stats.defenseMult -= GetPct(item, bItemAttributes.DefenseBonusPercent); // Defense reduces damage taken
|
||||
stats.defenseMult -= GetPct(item, bItemAttributes.DefenseBonusPercent);
|
||||
stats.faithMult += GetPct(item, bItemAttributes.FaithBonusPercent);
|
||||
stats.damageMult += GetPct(item, bItemAttributes.DamageBonusPercent);
|
||||
stats.speedMult += GetPct(item, bItemAttributes.MoveSpeedBonusPercent);
|
||||
stats.attackSpeedMult += GetPct(item, bItemAttributes.AttackSpeedBonusPercent);
|
||||
stats.faithRegenMult += GetPct(item, bItemAttributes.FaithRegenBonusPercent);
|
||||
stats.thornDamageMult += GetPct(item, bItemAttributes.ThornDamageBonusPercent);
|
||||
|
||||
// New Attributes
|
||||
stats.staminaMult += GetPct(item, bItemAttributes.StaminaBonusPercent);
|
||||
stats.soulfireDamageMult += GetPct(item, bItemAttributes.SoulfireDamageBonusPercent);
|
||||
}
|
||||
|
||||
// 4. Apply Harmonies (Based on Table)
|
||||
@@ -126,61 +137,61 @@ namespace Beyond
|
||||
int bright = items.Count(i => i.trinketColor == TrinketColor.Bright);
|
||||
int dark = items.Count(i => i.trinketColor == TrinketColor.Dark);
|
||||
|
||||
// --- TABLE LOGIC IMPLEMENTATION ---
|
||||
|
||||
// Balance: Azure + Crimson + Viridian (A C V) -> Bonus Water of Life Flask
|
||||
// Balance (A C V)
|
||||
if (azure >= 1 && crimson >= 1 && viridian >= 1)
|
||||
stats.effectBalance = true;
|
||||
|
||||
// Calmness: 3 Azure (A A A) -> Longer Shield
|
||||
// Calmness (A A A)
|
||||
if (azure >= 3)
|
||||
stats.effectCalmness = true;
|
||||
|
||||
// Trust: 2 Azure + 1 Crimson (A A C) -> Faith Vampirism
|
||||
// Trust (A A C)
|
||||
if (azure >= 2 && crimson >= 1)
|
||||
stats.effectFaithVampirism = true;
|
||||
|
||||
// Breeze: 2 Azure + 1 Viridian (A A V) -> Freezing blast free
|
||||
// Zora's Focus / Breeze (A A V) -> Covert Gaze Radius/Length
|
||||
if (azure >= 2 && viridian >= 1)
|
||||
stats.effectBreeze = true;
|
||||
|
||||
// Determination: 3 Crimson (C C C) -> Combo finish +5% dmg
|
||||
// Determination (C C C)
|
||||
if (crimson >= 3)
|
||||
stats.effectDetermination = true;
|
||||
|
||||
// Vitality: 2 Crimson + 1 Azure (C C A) -> Health Vampirism
|
||||
// Vitality (C C A)
|
||||
if (crimson >= 2 && azure >= 1)
|
||||
stats.effectHealthVampirism = true;
|
||||
|
||||
// Eagerness: 2 Crimson + 1 Viridian (C C V) -> Reduce Dash Cooldown
|
||||
// Eagerness (C C V)
|
||||
if (crimson >= 2 && viridian >= 1)
|
||||
stats.effectEagerness = true;
|
||||
|
||||
// Bloom: 3 Viridian (V V V) -> Spell cost reduced 20%
|
||||
// Bloom (V V V)
|
||||
if (viridian >= 3)
|
||||
stats.effectBloom = true;
|
||||
|
||||
// Growth: 2 Viridian + 1 Azure (V V A) -> Cast restores HP
|
||||
// Growth (V V A)
|
||||
if (viridian >= 2 && azure >= 1)
|
||||
stats.effectGrowth = true;
|
||||
|
||||
// Rose: 2 Viridian + 1 Crimson (V V C) -> Bonus Thorn Dmg
|
||||
// Rose (V V C)
|
||||
if (viridian >= 2 && crimson >= 1)
|
||||
{
|
||||
stats.effectRose = true;
|
||||
stats.thornDamageMult += 0.05f;
|
||||
}
|
||||
|
||||
// The Darkening: 3 Bright
|
||||
// The Darkening (3 Bright)
|
||||
if (bright >= 3)
|
||||
stats.effectDarkening = true;
|
||||
|
||||
// Eclipse: 2 Bright + 1 Dark
|
||||
// Eclipse (2 Bright + 1 Dark)
|
||||
if (bright >= 1 && dark >= 1)
|
||||
stats.effectEclipse = true;
|
||||
|
||||
// Angel Eye (Requires defining combo, placeholder logic)
|
||||
// if (bright >= 2 && azure >= 1) stats.effectAngelEye = true;
|
||||
}
|
||||
|
||||
// Helper: Convert Integer Attribute (5) to Float Percentage (0.05)
|
||||
private float GetPct(bItem item, bItemAttributes attrName)
|
||||
{
|
||||
var attr = item.GetItemAttribute(attrName);
|
||||
|
||||
44
Assets/Scripts/Utils/ParticlesPlayerFollower.cs
Normal file
44
Assets/Scripts/Utils/ParticlesPlayerFollower.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Beyond
|
||||
{
|
||||
public class ParticlesPlayerFollower : MonoBehaviour
|
||||
{
|
||||
[Header("Position Settings")]
|
||||
[Tooltip("How high above the player the rain cloud sits.")]
|
||||
public float heightOffset = 15f;
|
||||
|
||||
[Tooltip("Smooths the movement so rain doesn't snap instantly.")]
|
||||
public bool useSmoothing = false;
|
||||
public float smoothSpeed = 10f;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Auto-find Invector player if not assigned
|
||||
if (Player.Instance == null)
|
||||
{
|
||||
Debug.LogWarning("ParticlesPlayerFollower: No Player found! Make sure Player.Instance is set.");
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (Player.Instance == null) return;
|
||||
var target = Player.Instance.transform;
|
||||
// Calculate where the rain emitter should be
|
||||
// We take the player's X and Z, but override the Y with our offset
|
||||
Vector3 targetPosition = new Vector3(target.position.x, target.position.y + heightOffset, target.position.z);
|
||||
|
||||
if (useSmoothing)
|
||||
{
|
||||
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * smoothSpeed);
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.position = targetPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Utils/ParticlesPlayerFollower.cs.meta
Normal file
2
Assets/Scripts/Utils/ParticlesPlayerFollower.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e008257ca9c7464d8f9b914b5b218b6
|
||||
Reference in New Issue
Block a user