Untitled

 avatar
unknown
plain_text
2 years ago
6.9 kB
3
Indexable
	Void KAI_LandVehicleChase (Int Flags = 0, Int ChaseFlags = 0, Double TurnRadius = 10, Double FollowDist = 384, Double RetreatDist = 768)
	{
		Bool MovedAlready; //If one of the KAI_MoveTowards/Away calls was made. Don't call the rest.
		Double MajorThreatRange = (RetreatDist*4)*(RetreatDist*4);
		//Temporarily store the aggro multiplier that is changed by the fear code. Then reset it after ShouldAttack() finishes.
		Double OldAggro = AggressionMultiplier;
		
		//If your target isn't your goal. And it's dead or friendly. Stop chasing it.
		If (Target && Target != Goal && (IsDead(Target) || !IsActorHostile(Target))) Target = Null;
		
		//Handle making the vehicle run away from its' target if it's a major threat. Or its' powerless.
		If (!bNoFear && Target)
		{
			If (!(Flags & KAIC_NOCHASE))
			{
				//If you can't attack, run. Also run for a set amount of time since last being scared, to prevent rubberbanding around
				If (!CanAttack() ||
				//If the targets' threat level is over the threshold, and it's visible and nearby, GTFO.
				ThreatLevelThreshold != THREAT_ASSESS && AssessThreatLevel(Target, False) >= ThreatLevelThreshold && (Distance3DSquared(Target) < MajorThreatRange && CheckSight (Target)))
				{a_log ("oh god oh fuck");
					KAI_MoveAway (Target,runrad:256,detourfactor:0.5,anglelimit:TurnRadius,chaseflags:ChaseFlags);
					MovedAlready = True;
				}
			}
			
			If (Flags & KAIC_ATTACKWHENSCARED)
				AggressionMultiplier *= 0.5;
		}
		
		FollowPlayerControl (FollowDist); //Handle turning on bDontFollowPlayers if you are too close to your friendplayer.
		
		//If you can move and haven't done so already.
		If (!(Flags & KAIC_NOCHASE) && !MovedAlready)
		{
			If (!(IsPatrolling(Self) && bChaseGoal)) NearestEnemy = FindNearestEnemy (RetreatDist);
			//If you aren't patrolling and not allowed off your route, and there is an enemy nearby.
			If (NearestEnemy)
			{a_log ("the danger zone");
				KAI_MoveAway (NearestEnemy,runrad:256,detourfactor:0.5,anglelimit:TurnRadius,chaseflags:ChaseFlags); //Keep your distance.
				MovedAlready = True;
			}
			//If your turrets' target is too high up for it to reach.
			Else If (Turret && Turret.Target && Turret.ElevationState == Turret.ELEVATION_TOOHIGH)
			{a_log ("moving back so my turret can fire");
				KAI_MoveAway (Turret.Target,runrad:256,detourfactor:0.5,anglelimit:TurnRadius,chaseflags:ChaseFlags); //Back off to allow your turret to shoot.
				MovedAlready = True;
			}
			//TODO: Move this to the OnWander virtual I'm adding later.
			/*Else If (Flags & KAIC_CORPSESEEKER && !Target && !IsPatrolling (Self) && CurrentOrder == ORDER_WANDER)
			{
				//Don't have a corpse to crush already.
				If (!CorpseTarget)
				{
					If (CorpseTarget = FindNearestCorpse();)
						KAI_MoveTowards (CorpseTarget.Pos);
				}
				//There is an available corpse to head to and crush.
				Else
					KAI_MoveTowards (CorpseTarget.Pos);
			}*/
			//If none of the other conditions are true. Run the standard A_Chase code (Minus movement), and KAI_MoveTowards.
			Else
			{
				A_Chase (Null,Null,CHF_DONTMOVE|ChaseFlags);
				//Finding a new target should be handled by the above A_Chase call, however if no new target was found. Call OnWander().
				If (!Target && !(ChaseFlags & CHF_DONTIDLE))
					OnWander();
				
				//Finally, if you do have a target, DO move towards it, but with KAI_MoveTowards instead of the shitty native movement code.
				If (Target)
					{a_log ("time to chase you");KAI_MoveTowards (Target.Pos, anglelimit:TurnRadius, chaseflags:ChaseFlags);}
			}
			
			MovedAlready = True;
		}
		
		If (!(Flags & KAIC_NOTURRETRETARGET)) RetargetVehicleHull(); //If targeting another vehicles' turret. See if targeting the vehicle itself would be better.
		Actor CheckFrom = Turret; //Check from the turret if you should maybe stay still and shoot.
		If (!CheckFrom) CheckFrom = Self; //If you have no turret, check from yourself.
		If (StayStillAndShoot (CheckFrom)) Return;
		
		If (ShouldAttack()) //Run the unique attack decision code of the vehicle.
		{
			AggressionMultiplier = OldAggro; //Reset aggression chance.
			ChaseTimer = 0;
			CorpseTarget = Null;
			Return; //End the function if the vehicle should attack.
		}
		AggressionMultiplier = OldAggro; //Reset aggression chance.
		
		HandleChaseTimer();
	}

	void KAI_MoveTowards (Vector3 TargetPos, Double DetourFactor = 1.0, Double AngleLimit = 10, Int ChaseFlags = 0, Int Flags = 0)
	{
		If (ChaseFlags & CHF_DONTMOVE || KAI_Math.IsEmptyVector3 (TargetPos)) {a_log ("fail ?");Return;}
		
		double LastAngle = angle;
		double NextAngle = LastAngle;
		console.printf ("heading to %d %d %d",targetpos.x,targetpos.y,targetpos.z);
		//MoveCount is greater than 0 when avoiding an obstacle
		if (MoveCount)
		{
			MoveCount--;
		}
		else
		{
			lastturndir = 0;
			//move directly towards Other
			if (!(ChaseFlags & CHF_NORANDOMTURN)) NextAngle = GetAngleToPos(TargetPos,AngleLimit);
		}
		
		//When CHF_NORANDOMTURN is on. The actor can take a set amount of turns before no longer turning to face its' target.
		If (ChaseFlags & CHF_NORANDOMTURN && --TurnCount > 0) NextAngle = GetAngleToPos(TargetPos,AngleLimit);
		
		//absolute position of next movement
		vector2 NextPos = Vec2Angle(speed, NextAngle);
		bool moved = TryMove(NextPos, 0, false);
 
		//if I hit an obstacle while avoiding another, try moving straight towards Other
		if (!moved && MoveCount)
		{
			MoveCount = Int(random(16,32)*DetourFactor);
			NextAngle = GetAngleToPos(TargetPos,AngleLimit);
			NextPos = Vec2Angle(speed, NextAngle);
			moved = TryMove(NextPos, 0, false);
		}
		
		//If there's a limit to how much the actor can turn per step. Decide an amount of turns for CHF_NORANDOMTURN to make after it hits an obstacle.
		If (!moved && AngleLimit > 0 && ChaseFlags & CHF_NORANDOMTURN)
		{
			Switch (AngleLimit)
			{
				Case 20:
					TurnCount = Random (2,4);
					Break;
				Case 10:
					TurnCount = Random (3,6);
					Break;
				Case 5:
					TurnCount = Random (8,12);
					Break;
				Default:
					Break;
			}
		}
		
		//test movement angles until I find one that works, avoid that obstacle for MoveCount tics
		if (!moved && !(ChaseFlags & CHF_STOPIFBLOCKED))
		{
			MoveCount = Int(random(16,32) * DetourFactor);
 
			//try moving the same relative direction as last time
			if (lastturndir == 0) lastTurnDir = random(0,1) ? 1.0 : -1.0;
			
			//find viable movement direction
			for (double i = 1; i < 6; i++)
			{
				NextAngle = LastAngle + (i * 48 * lastturndir);
				NextPos = Vec2Angle(speed, NextAngle);
				moved = TryMove(NextPos, 0, false);
				if (moved) break;
				
				lastTurnDir *= -1.0;
				
				NextAngle = LastAngle + (i * 48 * lastturndir);
				NextPos = Vec2Angle(speed, NextAngle);
				moved = TryMove(NextPos, 0, false);
				if (moved) break;
			}
		}
 
		//face movement direction
		If (!(ChaseFlags & CHF_NODIRECTIONTURN)) angle = Normalize180(NextAngle);
	}