sirsavary
|
  |
| Joined: 27 May 2008 |
| Total Posts: 1222 |
|
|
| 15 Sep 2012 10:45 PM |
So as some of you might know I'm working on what I hope will be Roblox's best RPG. Right now I am tackling NPC's and such, and after plenty of forum browsing I have noticed that just about all NPCs date back to one person, miked (Creator of Ultimate Paintball, first place to 1 million visits). These NPCs are slow and inefficent; they scan everything in Workplace to look for a humanoid. They might attack each other! So, just rename the Humanoid object! Simple. But now you're weapons don't work. Alright, change them! But now you can't PVP. Well isn't that just great. So Roblox, scripters, today I present you with the following:
sightRange = 10 responseTime = 1
function findNearestPlayer(pos) for _, player in pairs(game.Players:GetPlayers()) do if (player.Character.Humanoid.Health > 0) then if (player:DistanceFromCharacter(pos) <= sightRange) then return player.Character.Torso end end end end
while true do wait(responseTime) local target = findNearestPlayer(script.Parent.Parent.Torso.Position) if target ~= nil then script.Parent.Parent.Humanoid:MoveTo(target.Position, target) end end
If there is any way at all to make this more efficent, for the love of god tell me. The only problem I have right now is NPC-NPC combat. I really wanted armies of Dwarves facing off against Orcs, but I guess I'll just have to suck it up and make do.
NOTE: The script is slightly modified from what I use. The real script is tied into a few variables within the NPC, stored as objects so that my NPC plugin can change them easily. No you can't have, wait until I finish the RPG first. |
|
|
| Report Abuse |
|
|
sirsavary
|
  |
| Joined: 27 May 2008 |
| Total Posts: 1222 |
|
|
| 15 Sep 2012 10:46 PM |
Woops, the following:
Improvements: -No longer scans everything -Only follows players -Configurable responseTime and sightRange -Doesn't try to wait(0.0000000000000000000000000001) |
|
|
| Report Abuse |
|
|
Droban
|
  |
| Joined: 12 Aug 2012 |
| Total Posts: 157 |
|
|
| 15 Sep 2012 10:56 PM |
I think we usually make something similar to that when we need to, since most of us don't use free models. You should really try to make it a free model and make it configurable and stuff. That'll improve a lot of games, instead of just (maybe) improving ours.
It'a also possible to use Region3's to detect only a limited number of parts, if you wanted to detect non-players. It's also possible to insert some value in every humanoid except players'.
sightRange = 10 responseTime = 1 function findNearestPlayer(pos) local region = Region3.new(pos-Vector3.new(-sightRange*.5,-sightRange*.5,-sightRange*.5),pos+Vector3.new(sightRange*.5,sightRange*.5,sightRange*.5)) for j, v in pairs(Workspace:FindPartsInRegion3(region)) do if v.Parent:FindFirstChild("Humanoid") and v.Parent.Humanoid:IsA("Humanoid") and not v.Parent.Humanoid:FindFirstChild("Monster") and v.Parent.Humanoid.Torso do return v.Parent.Humanoid.Torso end end end
while true do wait(responseTime) local target = findNearestPlayer(script.Parent.Parent.Torso.Position) if target ~= nil then script.Parent.Parent.Humanoid:MoveTo(target.Position, target) end end
That should get the closest non-monster-thing withing sightRange, including non-players. (So monster-things can attack npc's!)
What we really need is more advanced npc AI's. So they don't just follow you. |
|
|
| Report Abuse |
|
|
|
| 15 Sep 2012 10:57 PM |
I could be wrong, but doesn't this belong in game design?
-God Bless- |
|
|
| Report Abuse |
|
|
sirsavary
|
  |
| Joined: 27 May 2008 |
| Total Posts: 1222 |
|
|
| 15 Sep 2012 11:00 PM |
| Nice, never knew about regions. As for the advanced AI's, I've got a "Torch Orc" who stops a few blocks away from you and tries very hard to set you on fire via flamethrower. I have a peasant, who when provoked attacks with his right first, then his left, and finishes with a right kick, then repeats. I'm working on some other ones too, next up is an undead creature who breathes poisonus gas, after that is a creature which lunges at you and the freezes. As soon as you turn, lunges again. Only easy way to kill him is when he is in mid-lunge. |
|
|
| Report Abuse |
|
|
sirsavary
|
  |
| Joined: 27 May 2008 |
| Total Posts: 1222 |
|
|
| 15 Sep 2012 11:00 PM |
Last time I went to game design:
"Hi, I mad-" "n00b" "probably free modeled that" "I AM 1x1x1x1"
I just stay in Scripters now. It's nicer. |
|
|
| Report Abuse |
|
|
|
| 16 Sep 2012 06:26 AM |
| Yeah but we all can do this on the back of our hands with our eyes closed. |
|
|
| Report Abuse |
|
|
|
| 16 Sep 2012 07:14 AM |
I agree @ Trappingnoobs;
These NPCs aren't so hard and making them attack each other isn't any harder either. The thing I'm confused is legitimate pathfinding, such as A*, as they are very hard to implement in games as they are hard to be adjustable.
☜▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬☞ |
|
|
| Report Abuse |
|
|
jode6543
|
  |
| Joined: 16 Jun 2009 |
| Total Posts: 5363 |
|
|
| 16 Sep 2012 07:20 AM |
If you wanted to do EvE (Environment vs Environment, aka NPCvNPC), then you'd probably need a legit AI/pathfinder to pull it off successfully.
-Jode |
|
|
| Report Abuse |
|
|
|
| 16 Sep 2012 07:23 AM |
No, you can make a pseudo food chain system - if there's no one around, check for nearest monster under 20.
☜▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬☞ |
|
|
| Report Abuse |
|
|
sirsavary
|
  |
| Joined: 27 May 2008 |
| Total Posts: 1222 |
|
|
| 16 Sep 2012 10:15 AM |
| I understand that this is easy for just about everyone here to create, I was wondering if there was anything else that could be added to it to make it better. Last night I added raycasting to it, so you will only be attacked if you are seen. Today I am going to be adding alert statuses (When you are seen and run, the monster will slowly cool down and stop the pursuit) and if I have time, I will start working on the A* pathfinding (provided I can pull it off without killing the game). |
|
|
| Report Abuse |
|
|
|
| 16 Sep 2012 10:22 AM |
Here is something that HAS been done before, but is pretty novel enough that your system stands out:
Food chain system. Monster territorial system. Simple yet effective pathfinding system. Noise system. Chasebreak system. Mob system.
PROTIP: Don't work on A* unless you're ready for extensive late nights and coffee (omg coffee <3) and extensive debugging and code.
☜▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬☞ |
|
|
| Report Abuse |
|
|
sirsavary
|
  |
| Joined: 27 May 2008 |
| Total Posts: 1222 |
|
|
| 16 Sep 2012 10:27 AM |
Food chain is something I won't be adding, it's unnecessary. However, I will be doing a "factions" system that coincides with my RPG's story.
Orcs Hate: Goblins Dwarves
Goblins Hate: EVERYONE
Dwarves Hate: Orcs Goblins
Dwarves and Orcs start off as neutral towards you, but siding with one will make the other hostile. As for pathfinding, I might do something simpler than A*. We'll see. Noise/chasebreak system will be covered under my alert statuses. If you've ever played any game in the Metal Gear series, you'll know what I meant. And mob system? Like what I already have? or??
And I've worked on tens of client projects before. Due to the magic of timezones, I've had to stay up until ungodly hours to hand in a project to someone in Europe at the right time. And A* has already been done on Roblox before. I am likely going to take that script and improve it in very way possible. |
|
|
| Report Abuse |
|
|
|
| 16 Sep 2012 10:47 AM |
...
Isn't that the same as a food chain system?
Like, AI will act like animals and fight each other in accordance.
☜▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬☞ |
|
|
| Report Abuse |
|
|
sirsavary
|
  |
| Joined: 27 May 2008 |
| Total Posts: 1222 |
|
|
| 16 Sep 2012 10:50 AM |
| I suppose yeah, when you said food chain I thought of like, high level orcs snacking on low level orcs ahaha. |
|
|
| Report Abuse |
|
|
0LED
|
  |
| Joined: 15 Sep 2012 |
| Total Posts: 224 |
|
|
| 16 Sep 2012 10:57 AM |
>.>
It's the same. I'm banned by the way, like my namesnipe? :)
Also, do what I said about the territorial thing. Control AI in a group of mobs that adapts and evolves with the environment - raid other AI's territory, or get raided.
☜▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬☞ |
|
|
| Report Abuse |
|
|
sirsavary
|
  |
| Joined: 27 May 2008 |
| Total Posts: 1222 |
|
|
| 16 Sep 2012 11:08 AM |
Wait, you got banned in the space of 5 minutes? Jeeze, I can't even pull that off!
And that's what I have planned. AI battles are covered under the random events section. Players will be able to fight on the side that they are allied with. |
|
|
| Report Abuse |
|
|
sirsavary
|
  |
| Joined: 27 May 2008 |
| Total Posts: 1222 |
|
|
| 16 Sep 2012 11:43 AM |
| Just had an amazing lightbulb-over-head idea. Instead of A*, I'm going to use raycasting for pathfinding. I will post the script when I am done as I believe many will benefit from it. |
|
|
| Report Abuse |
|
|
|
| 16 Sep 2012 12:07 PM |
what kind of algorithm would you use in conjunction with raycasting?
¬ Scripter Tier-2, LuaLearners Elite ♣ scripting teacher/freelance worker ♣ send me trade requests! |
|
|
| Report Abuse |
|
|
sirsavary
|
  |
| Joined: 27 May 2008 |
| Total Posts: 1222 |
|
|
| 16 Sep 2012 12:43 PM |
Actually, I'm stuck on it now because I'm trying to find a way to make rays "persistent". However:
Cast rays in 8 cardinal directions from NPC's head, repeat with player's. If two rays cross, mark this point as a node. Move NPC to node, then cast all rays again (player may have moved). If two rays do not cross, cast 8 rays in cardinal directions from the points where the first 16 rays orginally hit. Look for intersecting points. If no path to player exists, forget it. Return to patrolling. If path does exist, follow it. If more than one path exists, follow one with least number of intersecting points/nodes.
If I was able to, I would do it with navigation meshes, but I can't seem to figure out how I would implement it. |
|
|
| Report Abuse |
|
|
|
| 16 Sep 2012 12:53 PM |
| Yes. I have some new updates on that. |
|
|
| Report Abuse |
|
|
|
| 16 Sep 2012 01:08 PM |
| your solution is very inefficient. |
|
|
| Report Abuse |
|
|
sirsavary
|
  |
| Joined: 27 May 2008 |
| Total Posts: 1222 |
|
|
| 16 Sep 2012 01:32 PM |
| Which is why I don't like it, it's a much better method to use in a game that has a persistent, never changing world. If I can't implement navigation meshes, I'm jsut going to scrap pathfinding. Most players won't run anyways, the majority of them will just charge in like a bull and try to kill the enemy. |
|
|
| Report Abuse |
|
|
|
| 16 Sep 2012 03:35 PM |
| Probably should read the entire thread before posting, but can't you just put a value in each NPC and have the script make sure they aren't fighting other NPC's by using the value? |
|
|
| Report Abuse |
|
|
sirsavary
|
  |
| Joined: 27 May 2008 |
| Total Posts: 1222 |
|
|
| 16 Sep 2012 05:03 PM |
Yep, that's what I used to do. Every NPC had a "friend" value. The issue here is that I made it so the only objects that get scanned are players. NPC's are not players, so they will never even run past the target checking logic. Also, here's the new script with raycasting and alert status (Minus pathfinding):
NPC = script.Parent.Parent sightRange = NPC.Variables.SightRange.Value responseTime = NPC.Variables.ResponseTime.Value alertStatus = 0 timesTried = 0
function findNearestPlayer(pos) for _, player in pairs(game.Players:GetPlayers()) do if (player.Character.Humanoid.Health > 0) then distanceApart = player:DistanceFromCharacter(pos) if (distanceApart <= sightRange) then local ray = Ray.new(NPC.Head.CFrame.p, (player.Character.Head.CFrame.p - NPC.Head.CFrame.p).unit * 500) local ignore = NPC local hit, position = Workspace:FindPartOnRay(ray, ignore) if (hit ~= nil) and (hit:IsDescendantOf(player.Character)) then NPC.Events.PlayerFound:Fire(distanceApart) alertStatus = 1 return player.Character.Torso elseif (alertStatus == 1)then timesTried = timesTried + 1 if (timesTried > 10) then NPC.Functions.StopMoving:Invoke() alertStatus = 0 end end end end end end
while true do wait(responseTime) local target = findNearestPlayer(NPC.Torso.Position) if target ~= nil then NPC.Humanoid:MoveTo(target.Position, target) end end
|
|
|
| Report Abuse |
|
|