By default the hostile npc's close in on the player from a far distance. I want to decrease this distance and I have looked into the code and I believe the piece of code that needs to be changed is:
public virtual Character GetClosestHostile()
{
// var visibleArea = GetVisibleMapArea();
var visibleArea = GetBattleArea();
var center = Actor.Center;
// Get the characters that we are even hostile towards and are in view
var possibleChars = Actor.Map.Spatial.GetMany
x => IsValidTarget(x) && IsHostileTowards(x) && x != Actor);
var closest = possibleChars.MinElementOrDefault(x => center.QuickDistance(x.Center));
return closest;
}
///
/// Gets a
///
///
public Rectangle GetVisibleMapArea()
{
var center = Actor.Center;
var min = center - _halfScreenSize;
var x = (int)Math.Max(0, min.X);
var y = (int)Math.Max(0, min.Y);
var w = (int)Math.Max(Actor.Map.Width, min.X + GameData.ScreenSize.X);
var h = (int)Math.Max(Actor.Map.Height, min.Y + GameData.ScreenSize.Y);
return new Rectangle(x, y, w, h);
}
I tried to change the variables in the public Rectangle GetVisibleMapArea() but I don't get the desired result. What I want is like if the player is in a distance of 200 pixels (not sure if that is the correct measurment) the NPC closes in to attack. Am I looking in the right place and if so. Can someone explain to me how I should visualize this rectangle and what i need to change to get the result I want.
Thanks in advance
Call the GetClosestHostile and test whether or not it is within your desired distance. Try not to change anything in AIBase too much.
Hey Skey, Yeah I figured out it was from the viewpoint of the enemycharacter what I actually wanted the know was what the variables x,y,h,w are (well I kinda know what they are) but especially the (int)Math.Max part does.
@aphro, I did try several values and looked for the desired effect but to no avail, and that is why i posted this question. I will try some more off course
and in the main time I hope someone can help me out with it, because I think it is also interesting for other people to know how to decrase the range of sight of the enemies.
Let's all use some CP and poke Spodi into making some more generic AIs and adding lotsa documentation on it? ![]()
Math.Max returns the larger of the two variables. Basically it ensures that x and y isn't set to anything less than 0 in this case. And h and w are either set to the height/ width of the current map respectively or the screensize
I dont think i#ve explained greatly. But basically its returning a whole rectangle of the visible screen unless we're at the edge of the map, in which case it returns a rectangle within the bounds of the map.
Thanks aphro for explaining the math.max that helps me better understand the code. I still can't seem to get it to work nicely though maybe the big man himself can help out a bit when he has the time
.
I think this would do what you want maybe? If i've understood correctly anyway.
var c = GetClosestHostile(); if (c.Center.QuickDistance(Actor.Center) < 200) { // Your movement code to "close in" here... }
Hi Aphro, that might indeed do the trick, it seems to work. I think we are on to something here
. The only problem is that I get a nullreference error at the line
if (c.Center.QuickDistance(Actor.Center) < 200)
-.- well since i worked some magic after getting tired of linux and managed to get windows back on my comp and c# and all the tools for this engine i'll take a look and see what i can do
if (c.Center.QuickDistance(Actor.Center) < 200)
The GetClosestHostile doesn't always return a character if it cant find one it will return null, just check for a null value for c.
if((c != null) && (c.Center.QuickDistance(Actor.Center) < 200)){ // Do your stuff }
Thanks for this thread everyone.
I took the original TestAI class, copied it and made a new MyAI class. Everything is the same as the original TestAI class except the following block of code where DoUpdate() has been modified and I've added the suggested code in CheckTargetDistance():
protected override void DoUpdate() { var time = GetTime(); // Ensure the target is still valid, or enough time has elapsed to check for a better target if ((_target != null && !IsValidTarget(_target)) || (_lastTargetUpdateTime + _targetUpdateRate < time)) { _lastTargetUpdateTime = time; _target = GetClosestHostile(); } // Check if we have a target or not if (_target == null) UpdateNoTarget(); else CheckTargetDistance(); } void CheckTargetDistance() { var c = GetClosestHostile(); if((c != null) && (c.Center.QuickDistance(Actor.Center) < 200)) { UpdateWithTarget();// Your movement code to "close in" here... } }
Seems to work okay, except the calls to UpdateNoTarget() seem a little unpredictable. Silly question... assuming _targetUpdateRate = 2000, how does that translate into real time?
NetGore almost always specifies time in milliseconds. So 2000 = 2 seconds.
Thanks Aphro that makes sense and that does seem to fix it.
It looks like the VisibleMapArea is from the point of view of the one using the method, which is the enemy in this case.
Click here for my Netgore Content Editor Tutorial video