Чертоги разума, хваты пустой руки, одержимость, книга с оглавлением
- Чертоги разума: дух в префабе chertogi под землёй, книга памяти, нож и плакат; кровать префаба - мебель necroPalaceBed (иначе становилась точкой возрождения); охрана выбрасывает и игроков (их нет в EntityAlives). - Хваты пустой руки по R: «отрицание» и «пиф-паф» - поза рук костями поверх аниматора, остальные кости заморожены, ЛКМ - заклинание, прицел краснеет на зомби. - «Отрицание»: зомби в ужасе бежит дальше 40 м и теряет игрока как цель. - «Пиф-паф»: одержимость зомби-гуманоидом - бег, прыжок, удар, дальняя атака, подрыв, крик крикуньи; тело цепенеет, зомби танкуют одержимого; область вокруг тела сжата; полоска здоровья; спавн и прорисовка у одержимого. - Книга с оглавлением (окно necroTome), глава «Некроэнергия». - Прорисовка дверей у змеи и одержимого (CheckLODs от камеры, а не от тела). - Почтовый ящик консоли и команды necrobones/necropose/necroshot для разработки. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c828202c66
commit
66a0dcf403
@@ -37,6 +37,15 @@ namespace NecromancerTome
|
||||
|
||||
public static Vector3 SnakePos;
|
||||
public float Until;
|
||||
/// <summary>Своя угроза вместо змеи (хват «отрицание», 03.10): бежать от этой точки.</summary>
|
||||
public bool HasThreat;
|
||||
public Vector3 Threat;
|
||||
public float Speed = FleeSpeed;
|
||||
/// <summary>Кого забыть, когда бегство кончится (хват «отрицание»: «должен терять меня как цель»).
|
||||
/// Он же угроза: бежать от его ТЕКУЩЕГО места.</summary>
|
||||
public EntityAlive Forget;
|
||||
/// <summary>Больше нуля - бежать, пока Forget ближе этого (и не дольше Until).</summary>
|
||||
public float FarDistance;
|
||||
Vector3 targetPos;
|
||||
int retargetTicks;
|
||||
|
||||
@@ -49,7 +58,7 @@ namespace NecromancerTome
|
||||
|
||||
public override bool CanExecute()
|
||||
{
|
||||
return Time.time < Until && FindFleePos();
|
||||
return Time.time < Until && !FarEnough() && FindFleePos();
|
||||
}
|
||||
|
||||
/// <summary>Сколько криков тревоги уже было в этом кадре: у толпы кричат не все.</summary>
|
||||
@@ -78,13 +87,18 @@ namespace NecromancerTome
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
if (Forget != null)
|
||||
{
|
||||
ForgetNow(theEntity, Forget);
|
||||
Forget = null;
|
||||
}
|
||||
theEntity.moveHelper.Stop();
|
||||
theEntity.SetLookPosition(Vector3.zero);
|
||||
}
|
||||
|
||||
public override bool Continue()
|
||||
{
|
||||
return Time.time < Until && !theEntity.IsDead();
|
||||
return Time.time < Until && !theEntity.IsDead() && !FarEnough();
|
||||
}
|
||||
|
||||
float _diagTime;
|
||||
@@ -104,7 +118,7 @@ namespace NecromancerTome
|
||||
Debug.Log("[NecromancerTome] NecroFleeSnakeTask: " + theEntity.entityId + " поз " + theEntity.position.ToString("F0") +
|
||||
" цель " + targetPos.ToString("F0") + " путь " + (path == null ? "нет" : path.NodeCountRemaining() + " узл.") +
|
||||
" считается " + PathFinderThread.Instance.IsCalculatingPath(theEntity.entityId) +
|
||||
" скор " + FleeSpeed.ToString("F2"));
|
||||
" скор " + Speed.ToString("F2"));
|
||||
}
|
||||
if (--retargetTicks > 0 || PathFinderThread.Instance.IsCalculatingPath(theEntity.entityId))
|
||||
{
|
||||
@@ -113,7 +127,7 @@ namespace NecromancerTome
|
||||
retargetTicks = RetargetTicks;
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
FindFleePos();
|
||||
theEntity.FindPath(targetPos, FleeSpeed, true, this);
|
||||
theEntity.FindPath(targetPos, Speed, true, this);
|
||||
if (sw.Elapsed.TotalMilliseconds > 3.0)
|
||||
{
|
||||
Debug.Log("[NecromancerTome] NecroFleeSnakeTask: долгий перерасчёт у " + theEntity.entityId + " - " + sw.Elapsed.TotalMilliseconds.ToString("F1") + " мс");
|
||||
@@ -122,7 +136,11 @@ namespace NecromancerTome
|
||||
|
||||
bool FindFleePos()
|
||||
{
|
||||
Vector3 away = theEntity.position - SnakePos;
|
||||
if (Forget != null && FarDistance > 0f)
|
||||
{
|
||||
Threat = Forget.position;
|
||||
}
|
||||
Vector3 away = theEntity.position - (HasThreat ? Threat : SnakePos);
|
||||
away.y = 0f;
|
||||
if (away.sqrMagnitude < 0.01f)
|
||||
{
|
||||
@@ -166,9 +184,58 @@ namespace NecromancerTome
|
||||
_e.aiManager.tasks.AddTask(Priority, task);
|
||||
Debug.Log("[NecromancerTome] NecroFleeSnakeTask: зомби " + _e.entityId + " в ужасе");
|
||||
}
|
||||
task.HasThreat = false;
|
||||
task.Speed = FleeSpeed;
|
||||
task.Forget = null;
|
||||
task.FarDistance = 0f;
|
||||
task.Until = Time.time + FearSeconds;
|
||||
}
|
||||
|
||||
/// <summary>Хват «отрицание» (03.10): напугать зомби жестом игрока - бежит от игрока быстрее обычного
|
||||
/// _seconds секунд, сразу и в конце бегства теряет игрока как цель.</summary>
|
||||
bool FarEnough()
|
||||
{
|
||||
return FarDistance > 0f && Forget != null && (theEntity.position - Forget.position).sqrMagnitude > FarDistance * FarDistance;
|
||||
}
|
||||
|
||||
public static void ScareFrom(EntityAlive _e, EntityAlive _threat, float _seconds, float _speed, float _farDistance = 0f)
|
||||
{
|
||||
if (_e.aiManager == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_e.ConditionalTriggerSleeperWakeUp();
|
||||
NecroFleeSnakeTask task = _e.aiManager.tasks.GetTask<NecroFleeSnakeTask>();
|
||||
if (task == null)
|
||||
{
|
||||
task = new NecroFleeSnakeTask();
|
||||
task.Init(_e);
|
||||
_e.aiManager.tasks.AddTask(Priority, task);
|
||||
}
|
||||
task.HasThreat = true;
|
||||
task.Threat = _threat.position;
|
||||
task.Speed = _speed;
|
||||
task.Forget = _threat;
|
||||
task.FarDistance = _farDistance;
|
||||
task.Until = Time.time + _seconds;
|
||||
ForgetNow(_e, _threat);
|
||||
// Сетка поиска пути строится вокруг игроков - здесь она есть; но зомби может быть на краю.
|
||||
AstarManager.Instance?.AddLocation(_e.position, 40);
|
||||
Debug.Log("[NecromancerTome] NecroFleeSnakeTask: зомби " + _e.entityId + " отрицание - бежит до " + _farDistance + " м (не дольше " + _seconds + " с), скор " + _speed);
|
||||
}
|
||||
|
||||
public static void ForgetNow(EntityAlive _e, EntityAlive _who)
|
||||
{
|
||||
if (_e.GetAttackTarget() == _who)
|
||||
{
|
||||
_e.SetAttackTarget(null, 0);
|
||||
}
|
||||
if (_e.GetRevengeTarget() == _who)
|
||||
{
|
||||
_e.SetRevengeTarget(null);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return base.ToString() + ", flee to " + targetPos + ", " + (Until - Time.time).ToString("F1") + " s";
|
||||
|
||||
Reference in New Issue
Block a user