protected override void OnTargetTrigger(Bio target, int triggerIndex) { base.OnTargetTrigger(target, triggerIndex); EntityUtils.GetEntitiesInCircle(this._buff.battle.GetEntities(), this._buff.property.position, this._buff.radius, ref this._temp1); EntityUtils.FilterTarget(this._buff.caster, CampType.Hostile | CampType.Neutral, EntityFlag.Hero, ref this._temp1, ref this._temp2); if (this._temp2.Count > 0) { int index = this._buff.battle.random.Next(0, this._temp2.Count); //上限是闭区间 this.CreateMissile(( Bio )this._temp2[index]); } else { this._temp2.Clear(); EntityUtils.FilterTarget(this._buff.caster, CampType.Hostile, EntityFlag.SmallPotato, ref this._temp1, ref this._temp2); if (this._temp2.Count > 0) { int index = this._buff.battle.random.Next(0, this._temp2.Count); this.CreateMissile(( Bio )this._temp2[index]); } } this._temp1.Clear(); this._temp2.Clear(); }
protected override void OnUpdate(UpdateContext context) { FoxFire foxFire = ( FoxFire )this.owner; foxFire.property.Equal(Attr.Position, Vec3.Normalize(this.angleSpeed * (foxFire.property.position - this.caster.property.position)) * this.distance + this.caster.property.position); this._time += context.deltaTime; if (this._time < this._delay) { return; } this._time = 0f; EntityUtils.GetEntitiesInCircle(foxFire.battle.GetEntities(), foxFire.property.position, foxFire.detectRange, ref this._temp1); EntityUtils.FilterTarget(foxFire, CampType.Hostile | CampType.Neutral, EntityFlag.Hero, ref this._temp1, ref this._temp2); if (this._temp2.Count > 0) { int index = foxFire.battle.random.Next(0, this._temp2.Count); //上限是闭区间 foxFire.Emmit(( Bio )this._temp2[index]); } else { this._temp2.Clear(); EntityUtils.FilterTarget(foxFire, CampType.Hostile, EntityFlag.SmallPotato, ref this._temp1, ref this._temp2); if (this._temp2.Count > 0) { int index = foxFire.battle.random.Next(0, this._temp2.Count); foxFire.Emmit(( Bio )this._temp2[index]); } } this._temp1.Clear(); this._temp2.Clear(); }
public override Vec3 Steer() { Entity self = this._behaviors.owner; float detectRadius = MIN_DETECTION_BOX_LENGTH * (1 + self.property.speed / self.maxSpeed); EntityUtils.GetEntitiesInCircle(self.battle.GetEntities(), self.property.position, detectRadius, ref this._temp); this.DebugDrawDetectRadius(detectRadius); Bio closestIntersectingObstacle = null; float distToClosestIp = float.MaxValue; Vec3 localPosOfClosestObstacle = Vec3.zero; int count = this._temp.Count; for (int i = 0; i < count; i++) { Bio bio = this._temp[i] as Bio; if (bio == null || bio == self || bio.isDead || !bio.volumetric || bio.property.dashing > 0 || bio.property.ignoreVolumetric > 0) { continue; } Vec3 localPos = self.PointToLocal(bio.property.position); if (localPos.x >= 0) { float expandedRadius = bio.size.z + self.size.z; if (MathUtils.Abs(localPos.z) < expandedRadius) { float cX = localPos.x; float cZ = localPos.z; float sqrtPart = MathUtils.Sqrt(expandedRadius * expandedRadius - cZ * cZ); float ip = cX - sqrtPart; if (ip <= 0.0f) { ip = cX + sqrtPart; } if (ip < distToClosestIp) { distToClosestIp = ip; closestIntersectingObstacle = bio; localPosOfClosestObstacle = localPos; } } } } this._temp.Clear(); if (closestIntersectingObstacle != null) { Vec3 steeringForce = Vec3.zero; const float minLocalXDistance = .3f; //限定最小的x轴距离,值越小,下面得到的x轴因子越大,侧向力就越大 float multiplier = 1.5f / MathUtils.Min(minLocalXDistance, localPosOfClosestObstacle.x); //侧向力和障碍物的x距离成反比,越近x轴的因子越大,侧向力越大 steeringForce.z = -closestIntersectingObstacle.size.z * multiplier / localPosOfClosestObstacle.z; //侧向力和障碍物的半径成正比,z轴距离成反比 const float brakingWeight = .2f; //制动力因子,值越大,速度减少越快 steeringForce.x = (closestIntersectingObstacle.size.x - localPosOfClosestObstacle.x) * brakingWeight; steeringForce = self.VectorToWorld(steeringForce); this.DebugDrawForce(steeringForce * 3); return(steeringForce); } return(Vec3.zero); }
private void SelectTargets(Bio mainTarget, bool detectInOut, ref List <Bio> result) { if (detectInOut) { this._tempOldTargets.AddRange(result); result.Clear(); } switch (this._buff.rangeType) { case RangeType.Single: //检查指定的目标是否符合条件 //在隐身等状态下也能选中,因此不能使用CanAttack方法 if (!mainTarget.isDead && EntityUtils.CheckCampType(this._buff.caster, this._buff.campType, mainTarget) && EntityUtils.CheckTargetFlag(this._buff.targetFlag, mainTarget)) { result.Add(mainTarget); } break; case RangeType.Circle: { bool targetAdded = false; if (mainTarget != null && EntityUtils.CanAttack(this._buff.caster, mainTarget, this._buff.campType, this._buff.targetFlag)) { targetAdded = true; result.Add(mainTarget); //如果指定的目标符合条件则优先添加到目标列表 } int maxTargetNum = mainTarget != null ? this._buff.maxTriggerTargets - 1 : this._buff.maxTriggerTargets; if (maxTargetNum > 0) { EntityUtils.GetEntitiesInCircle(this._buff.battle.GetEntities(), this._buff.property.position, this._buff.radius, ref this._temp1); if (targetAdded) { this._temp1.Remove(mainTarget); //之前已经添加目标了 } EntityUtils.FilterTarget(this._buff.caster, this._buff.campType, this._buff.targetFlag, ref this._temp1, ref this._temp2); this._temp1.Clear(); EntityUtils.FilterLimit(ref this._temp2, ref this._temp1, maxTargetNum); int count = this._temp1.Count; for (int i = 0; i < count; i++) { result.Add(( Bio )this._temp1[i]); } this._temp1.Clear(); this._temp2.Clear(); } } break; case RangeType.Sector: //todo break; } if (detectInOut) { int tc = result.Count; for (int i = 0; i < tc; i++) { Bio mTarget = result[i]; if (!this._tempOldTargets.Contains(mTarget)) { this._tempEnter.Add(mTarget); } } tc = this._tempOldTargets.Count; for (int i = 0; i < tc; i++) { Bio mTarget = this._tempOldTargets[i]; if (!result.Contains(mTarget)) { this._tempExit.Add(mTarget); } } this.HandleTargetInOut(this._tempEnter, this._tempExit); this._tempEnter.Clear(); this._tempExit.Clear(); this._tempOldTargets.Clear(); } }