|
||
|
|||||||
| Custom Script Releases This forum is where you can release your custom scripts for other users to use. Please note: By releasing your scripts here you are submitting them to the public and as such agree to make them public domain. The RunUO Team has made its software GPL for you to use and enjoy you should do the same for anything based off of RunUO. |
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 (permalink) |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
Courageous' (aka Joe Kraska's) True LOS Version: 1.4B (BETA) -- 30 Sep 2007 ABOUT THIS SOFTWARE This is a "true" Line of Sight system for RunUO. In the core distribution (and OSI itself), a player can see mobiles which they shouldn't be able to see, such as in the case of players and monsters on the other side of a wall. The reason that this is the case is that the traditional calculations for LOS on the scale of a multiplayer server are too expensive. This system remedies that. UPDATES 30 Sep 2007. Uploaded the 1.4B "beta" version.
WHAT HAPPENS WHEN YOU INSTALL IT When installed: Players should not see other players or mobiles, if a wall, tree, or other visual obstruction is in the way. There is nothing particularly innovative about this. What is innovative about this is the performance. What you are currently looking at may be the fastest implementation of 2D line of sight in the world. Some shards have tried LOS before, the obvious way, and encountered terrible lag. This system should be very, very fast. Is it fast enough for a "production shard"? In truth, I don't know. I have tested it under synthethetic load, and got it to support 100's of player mobiles on my dual core computer with 1G of RAM. So onward: Trees block line of sight. Houses, land terrain, and items with the appropriate flags set block line of sight. Other mobiles do not block line of sight. Only player mobiles use the line of sight system. AI mobiles do not use this LOS system. As you explore and play with the software, one should understand a bit about how it is expected to work. The software cuts a 2d plane from the player's eyes, and anything intersecting that plane will block LOS to the target, even if the target is not in the plane. By and large, this phenomenon is mostly not noticeable, but does lead to some interesting inbalances regarding who can see whom when one player is at a higher terrain level than another. The advantage is to the higher ground. An example where the higher ground might get an advantage that is a little weird: Code:
_____________A_
|
|___________________B____________
Now note the subtle change in the arrangement below: Code:
______________A
|
|___________________B____________
As far as the imbalance in the first example goes, gm's might find this imbalance unfair or potentially exploitable. If that is the case, there is an option in the config file to use "symmetric" LOS. In symmetric LOS, each viewer uses the worst of both their view and the viewees view of eachother: if one party can't see the other, neither can. Finally, another word about the config file. There is a "White List" and a "Black List". The white list is for items and statics that are flagged as LOS blocking in the muldata files, but you don't want to block LOS. The black list is vice versa: add things here you want to block LOS. The values already present are for the trees. DETAILS... for the MASOCHISTICALLY CURIOUS This system was inspired originally by some notes collected by Amit Patel, who has done the world a favor in introducing some programming notes on pathfinding and LOS and other such at his home page here: http://www-cs-students.stanford.edu/~amitp/gameprog.html The basic idea is to record the fact of a "shadow" (an area that cannot be seen) for any obstruction one might find in the field of view. One could then combine these shadows together for the sum of obstructions, in effect moving the cost of LOS over to the obstructions instead of the LOS checks. In theory, if one can create the sum of shadows quickly enough, every LOS check in the same position would be "free" thereafter. What follows is a long series of optimizations and hacks in order to make this work. Let's look at the main idea: Figure-1: Code:
// {{-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,#,#,#,#},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,#,#,#,#,#},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,#,#,#,#,#},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,#,#,#,#,#,#},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,#,#,#,#,#,#},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,#,#,#,#,#,#,#},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,#,#,#,#,#,#,#},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,#,#,#,#,#,#,#,#},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,#,#,#,#,#,#,#,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,#,#,#,#,#,#,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,#,#,#,#,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,#,#,#,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,#,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,#,#,#,#,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,X,#,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,O,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-},
// {-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-}},
Compare that with this method, where for any given obstruction, in any given relative position, the shadow is known once and for all, and never needs to be calculated more than once! (In fact, LOS never actually calculates shadows, but rather uses a special code generator to produce them in a binary compact "precompiled" form, for performance reasons). Now lets look at this: Figure-2: Code:
# # # # # # # # - - - - - - - - # # - - - - - - - - - - - - # # # # # # # # # - - - - - - - # # - - - - - - - - - - - - # # # # - # # # - - - - - - - - # # - - - - - - - - - - - - # # # # # # # # # - - - - - - - # # - - - - - - - - - - - # # # # # # # # # - - - - - - - - # # - - - - - - - - - - # # # # # # # # # # # - - - - - - - - - - - - - - - - - # # # # # # # # # # # # - - - - - - - - - - - - - - - - - # # # # - # # # # # # # # # - - - - - - - - - - - - - - - # # # - - - # # # # # # # # - - - - - - - - - - - - - - - # # # - - - # # # # # # # # # - - - - - - - - - - - - - - # # # - - # # # # # # # # # # # - - - - - - - - - - - - - # # - - # # # # - # # # # # # # # - - - - - - - - - - - - - # - - - # # - - - # # # # # - # # - - - - - - - - - - - - - - - - - - - - - - # # # # # # # # - - - - - - - - - - - - - - - - - - - - - - - - # # # # # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # # - - - - - - - - - - - - - - - - - - - - - - - - - - - # # # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # - - - - - - - - - - - - - - - - - - - - - - - - - # - # # # - - - - - - - # # - - - - - - - - - - - - - - - - # # # - - - - - - - - # # - - - - - - - - - - - - - - - - - - - - - # - - - - - # # # - - - - - - - - - - - - - - - - - # - - # # - - - # # # # - - - - - # # - - - - - - - - - - - # - # # - - - # # # # # - - - - - # # - - - - - - - - - - - - # - - - - # # # # # - - - - - - # # - - - - - - - - - - - - - - - - # # - # # # - - - - - - # # - - - - - - - - - - - - - - - # # - # # # - - - - - - - # # - - - - - - - - - - - - - - # # - - # # # - - - - - - - # # - - - - - - - - - - - - This matrix was created using bits of code like this: Figure-3: Code:
// delegate( int[,] shadow )
// {
// shadow[0,0] |= 510;
// shadow[1,0] |= 1022;
// shadow[2,0] |= 1022;
// shadow[3,0] |= 2046;
// shadow[4,0] |= 2046;
// shadow[5,0] |= 4094;
// shadow[6,0] |= 4094;
// shadow[7,0] |= 8190;
// shadow[8,0] |= 8188;
// shadow[9,0] |= 16368;
// shadow[10,0] |= 16320;
// shadow[11,0] |= 32512;
// shadow[12,0] |= 31744;
// shadow[13,0] |= 61440;
// shadow[14,0] |= 16384;
// },
Note how there is no unecessary code to stride through the matrix. In cases other than this, the strides aren't always by +1, and would require other bits of code to execute. This is avoided by using a code-generated set of commands for every possible obstruction in the field of view. This is very, very fast. The last bit of optimization is the lookup. Here it is: Figure-4: Code:
// delegate ( ulong[,] shadow )
// {
// if( ( shadow[13,0] & 16777216ul ) == 16777216ul ) return true; else return false;
// },
An astute observer will note that the cost of establishing the mask is directly proportional to the number of obstructions, and has little indeed to do with the number of things being obstructed. This is true. The cost of establishing the mask is approximately 9 X the number of obstructions. This '9' is the average number of shadowmask commands in the generated code for a matrix of 37x37. The Figure 3 also happens to be (about) the worst case. That's a pretty good worst case! The above figures describe the main idea of True LOS. In addition to the main ideas, there are a number of interesting optimizations attached. This is the main one: The most notable optimization is a cache. The base world of UO doesn't change very much. That being the case, if a player has tried a LOS from particular location on the map, it is likely that future LOS attempts in the same location will produce the same results. It is further likely that other players will attempt to LOS from the same position. An MRU "most recently used" cache was developed that stores the most frequently used LOS matrices and reuses them. This further increases performance of the system by a good order of magnitude. There are a few other optimizations related to runuo itself, which will mostly only be of interested to core developers. They are commented in the code, and I encourage you to take a peek if you're into this kind of stuff. FREE SOFTWARE This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. INSTALLING THIS IS A CORE MOD. PLEASE PAY ATTENTION! Steps:
KNOWN DEFECTS, WORK IN PROGRESS, & PLANS Reported and verified:
I have some thoughts and ideas regarding players with high Detect Hidden skills perhaps getting the ability to escape the LOS system for a limited range, perhaps dependent on the Hide/Stealth skills of the target. One user recommended that all players in a common party be able to see eachother. This is being considered. C// Last edited by Courageous; 09-30-2007 at 02:16 PM. |
|
|
|
|
|
#4 (permalink) |
|
Forum Novice
|
I have one suggestion, still havn't got it into my server yet, but it immediately came to mind.
Make it so it's appliable optionally on a per facet basis. So I could for example say, on Trammel, you get old style LOS, but on Felucca, you get this new style.
__________________
|
|
|
|
|
|
#5 (permalink) | |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
Quote:
C// |
|
|
|
|
|
|
#7 (permalink) |
|
Forum Novice
Join Date: May 2005
Location: Canada
Age: 24
Posts: 543
|
Once again, a masterpiece, I'll be checking this out shortly. Thanks for the major contribution, I was waiting some time to see this puppy ;D
Thanks again!
__________________
A sense of community is the lifeblood of RunUO. http://www.runuo.com/forums/announcements/67400-something-all-you-chew.html Satire, man's greatest weapon (Flame Wars!) The darkness is patient and in the end it always wins...but even the smallest light can overcome the blackest shadow. |
|
|
|
|
|
#8 (permalink) |
|
Forum Expert
|
wow, this looks amazing...!
Thanks Lia
__________________
;)My C# Bookshelf (carpented by Soultaker);) BTW: Please ask questions in the adequat forum and not on a private message! Otherwise nobody can learn from it!
|
|
|
|
|
|
#9 (permalink) |
|
Forum Novice
|
Well, either I installed it wrong, or it has a really annoying problem.
When you walk around, stuff spams coming into view (Showing names of Incoming Mobiles.) Makes mobs walk in place, and just generally looks very bad. But it does seem to work. Any thing you can do about this problem? Or did I mess up installing it?
__________________
|
|
|
|
|
|
#11 (permalink) | |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
Quote:
[I often test with PlayUO; a quick double check in the ordinary client ruled out a problem there] C// Last edited by Courageous; 09-03-2006 at 12:12 PM. |
|
|
|
|
|
|
#12 (permalink) |
|
Forum Expert
Join Date: May 2005
Age: 29
Posts: 949
|
Isn't it the normal behavior, that a mobile (at least with a human body) that comes into view for the first time is display "walking"? Try placing a vendor and change your map. If you change it back, the vendor will be displayed with a part of the "walking" animation...
|
|
|
|
|
|
#14 (permalink) |
|
Forum Expert
Join Date: May 2005
Age: 29
Posts: 949
|
I'm not not sure myself: Try to change the map. Then go back, so that all the vendors are sent to the client again. When I try this, all the vendors look like they are moving on the step for a short period of time...
|
|
|
|
|
|
#15 (permalink) |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
Hmm. But I can only change the map if I am Admin. If I am Admin, LOS ought not be working. How are you changing the map?
I can turn LOS on for Admin's to test this, but this is a rather odd test. ![]() [addendum] I *think* I see what's being referenced. If I run around a tree, the vendor is in the walking position. Isn't this the ordinary consequence of the MobileIncoming packet? I'm doing nothing unusual here, just either permitting or denying the server the ordinary code. Is this not the expected behavior? C// Last edited by Courageous; 09-03-2006 at 12:57 PM. |
|
|
|
|
|
#17 (permalink) |
|
Forum Expert
Join Date: Jan 2004
Location: UK, Essex
Age: 19
Posts: 1,166
|
Hmm, would this be possible to incorporate into A_Li_Ns Completely Custom instead of required a recompile of the core?
__________________
It is not the hand that creates worlds, It is the mind controlling it ! The New Dawn Network |
|
|
|
|
|
#18 (permalink) | |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
Quote:
Perhaps after some testing and validation by the community, I can make the system so that is configurable as "on or off". If I did this, perhaps it could be put into the core, as a configurable option. C// Last edited by Courageous; 09-03-2006 at 02:55 PM. |
|
|
|
|
|
|
#19 (permalink) |
|
Forum Expert
Join Date: Jan 2004
Location: UK, Essex
Age: 19
Posts: 1,166
|
Ok then, I'll compile an exe and give it a go.
I think it would be a brilliant idea to have an option for turning it on or off, plus it would probably be a good idea to allow staff members to not be affected by the LOS checks.
__________________
It is not the hand that creates worlds, It is the mind controlling it ! The New Dawn Network |
|
|
|
|
|
#20 (permalink) |
|
Forum Expert
Join Date: Nov 2005
Location: San Diego, CA
Posts: 1,824
|
Anyone above Player is unaffected (which means if you are an Admin or what not, you need a Staff Cloak or some such to see the system in action). Read the PlayerMobile.cs mod. You can temporarily disable a line there to make it so that Staff are affected if you'd like to test it that way.
That should work "correctly," which is to say a hidden staff member of higher level than another should stay hidden. And so forth. Many of these defects were encountered during the alpha. The only known defect at this point is the one Cheetah is referring to. I didn't quite understand Cheetah's remarks regarding the all-names display, so I'm waiting on a screenshot. Addendum: During a code review comparing and contrasting Mobile.CanSee() to my new PlayerMobile.CanSee(), I see there are some minor details regarding hidden players and so forth that I need to attend to. Expect an update soon. Further Addendum: I believe I have replicated the described problem. If you quickly run in and out of LOS, all names can replicate, with "Jed the Baker" appearing several times above the mob's head and so forth. While the little stepping thing I regard as mostly unnoticeable, I see the duplicated name would be quite annoying. Looking into it. C// Last edited by Courageous; 09-04-2006 at 01:09 AM. |
|
|
|
|
|
#21 (permalink) |
|
Forum Novice
|
In your further addendum, Couragous, you describe what's happening on my server, but it doesnt matter if I lose line of sight or not, every step I take, the mob's name is shown AGAIN above it's head. I'll get you a screen shot in prolly an hour or two from this post. Have to go to work where my PC is.
I hope we can fix this, cuz this system ROXXORS!! ![]()
__________________
|
|
|
|