public void CreateDialogueBehavior(MentalType mentalType) { if (mentalType == MentalType.Normal) { return; } string textIdentifier = $"dialogmentalstate{mentalType.ToString().ToLowerInvariant()}"; character.Speak(TextManager.Get(textIdentifier), delay: Rand.Range(0.5f, 1.0f), identifier: textIdentifier, minDurationBetweenSimilar: 35f); }
public bool CreateCombatBehavior(MentalType mentalType) { Character mentalAttackTarget = Character.CharacterList.Where( possibleTarget => HumanAIController.IsActive(possibleTarget) && (possibleTarget.TeamID != character.TeamID || mentalType == MentalType.Berserk) && humanAIController.VisibleHulls.Contains(possibleTarget.CurrentHull) && possibleTarget != character).GetRandom(); if (mentalAttackTarget == null) { return(false); } var combatMode = AIObjectiveCombat.CombatMode.None; bool holdFire = mentalType == MentalType.Afraid && character.IsSecurity; switch (mentalType) { case MentalType.Afraid: combatMode = character.IsSecurity ? AIObjectiveCombat.CombatMode.Arrest : AIObjectiveCombat.CombatMode.Retreat; break; case MentalType.Desperate: // might be unnecessary to explicitly declare as arrest against non-humans combatMode = character.IsSecurity && mentalAttackTarget.IsHuman ? AIObjectiveCombat.CombatMode.Arrest : AIObjectiveCombat.CombatMode.Defensive; break; case MentalType.Berserk: combatMode = AIObjectiveCombat.CombatMode.Offensive; break; } // using this as an explicit time-out for the behavior. it's possible it will never run out because of the manager being disabled, but combat objective has failsafes for that mentalBehaviorTimer = MentalBehaviorInterval; humanAIController.AddCombatObjective(combatMode, mentalAttackTarget, allowHoldFire: holdFire, abortCondition: obj => mentalBehaviorTimer <= 0f); string textIdentifier = $"dialogmentalstatereaction{combatMode.ToString().ToLowerInvariant()}"; character.Speak(TextManager.Get(textIdentifier), delay: Rand.Range(0.5f, 1.0f), identifier: textIdentifier, minDurationBetweenSimilar: 25f); if (mentalType == MentalType.Berserk && !character.HasTeamChange(MentalTeamChange)) { // TODO: could this be handled in the switch block above? character.TryAddNewTeamChange(MentalTeamChange, new ActiveTeamChange(CharacterTeamType.None, ActiveTeamChange.TeamChangePriorities.Absolute, aggressiveBehavior: true)); } return(true); }
private void UpdateMentalState() { MentalType newMentalType = GetMentalType(character.CharacterHealth.GetAffliction("psychosis")); bool createdCombat = false; switch (newMentalType) { case MentalType.Normal: case MentalType.Confused: // remove combat if we became normal again mentalBehaviorTimer = 0f; break; case MentalType.Afraid: case MentalType.Desperate: case MentalType.Berserk: // berserk is not removed unless we drop to normal behavior again if (CurrentMentalType == MentalType.Berserk) { newMentalType = MentalType.Berserk; } // give players a full interval to react to mental changes if (newMentalType == CurrentMentalType) { createdCombat = CreateCombatBehavior(CurrentMentalType); } break; } if (!createdCombat) { CreateDialogueBehavior(newMentalType); } if (newMentalType != MentalType.Berserk) { character.TryRemoveTeamChange(MentalTeamChange); } CurrentMentalType = newMentalType; }
private MentalType GetMentalType(Affliction affliction) { if (affliction == null) { return(MentalType.Normal); } // test this later int psychosisIndex = (int)(affliction.Strength / (affliction.Prefab.MaxStrength / MentalTypeCount) * Rand.Range(1f, 1.2f)); psychosisIndex = Math.Clamp(psychosisIndex, 0, 4); MentalType mentalType = psychosisIndex switch { 0 => MentalType.Normal, 1 => MentalType.Confused, 2 => MentalType.Afraid, 3 => MentalType.Desperate, 4 => MentalType.Berserk, _ => throw new ArgumentOutOfRangeException(psychosisIndex.ToString()), }; return(mentalType); }