| 03-17-2006, 03:20 AM | #1 |
Documentation Basic
Basics: Okay there are very few things you actually need to know to play which is sortof a good thing, that is it would be if the FPSControl program was perfect, too bad it's not. StonedStoopid didn't quite finish the thing so everyone once in a while it won't find the memory location but we'll get to that later. Let's start with the basics. Open the map, press test map (or run it from inside warcraft) then as it opens up and everything loads alt+tab and run the control program. Once that opens up press the Find Memory Locations button, it will take some time but it will ussually find the memory location and once it does it will display it in the window. Then simply go back to the game, press tab in game then use ASDW and the mouse to run around till your heart explodes from joy, or boredom. Also note, left click is fire, right click is jump. Now comes option B. What happens if the control program doesn't find the memory location. In this case you will need a program called tsearch which you can get here http://os2.tucows.com/preview/48262.html this handy program basically does the same type of searching that the control program does but better. What you're going to do is then open up tsearch, press the big "Open Process" button, select war3.exe from the list, then press the small spy glass and search for "999999" as an Exact Value of 4 bytes. Once it finds about 4 or 5 locations, the first one should be the one your looking for. Type in that memory location into the window at the bottom of the control program, and press Set Addr. Then continue on as if the program just found the memory location the conventional way. Sounds fun doesn't it? =) Making your own map: Okay there are a few things you need to know before you make your own map, and simply speaking that is making your own height map of that map and then designating which unit is the FPSUnit. The second part is simple so we'll start with that first. In the trigger editor at the very bottom of the Initialize Variables trigger there's some text that looks like this: Code:
Set FPSunit[1] = Marine 0000 <gen> Now the hard part, once you've made your map and checked your list twice...err yeah. Once you've done that and finalized your terrain (anything except terrain can change without requiring a new height map) simply save your map and exit out of the editor. Once outside of the editor you will need an MPQ Extractor/Viewer whatever and extract the war3Map.w3e file that lies within the map file. Then use the attached W3EReader.exe program, (open it and browse for the w3e then click the button), to create a text file called variables.txt. Now all you have to do is open up this file and use the important looking contents within to replace the code that is already in the Initialize Height Variables trigger. It should look very similar so I doubt it will be hard to figure out which part to replace. Then, if you've exported and imported the triggers properly. Viola it will work. Currently implemented play options: Otherwise known as, "What you can do." The rundown is simple, I'll start with the ingame stuff all of which is contained in the "Console" section of triggers for you to look at, you have a few basic inputs to play around with and here they are: /fpv Changes to first person viewNow the slightly more in depth stuff, the variables (some of which are changed by the above text inputs) are really what interface with the engine. These are simply global variables that can be changed by hand or in game using triggers to alter the engine's internal workings, here is a rundown of all the variables that you can change. If any are not listed here, don't fuck with them. StopSlope Changed by /FF, described thereinAnd once again, we go even deeper, although I pride myself on having very few of these, there are a few places where you actually need to change numbers within the code itself to change the engine. -Anything within the fire trigger. There was supposed to be a seperate trigger for each weapon which is why this works. This will be explained in detail in another section. Documentation Advanced
Custom Script Code -GetHeightThis function has become obsolete and has been renamed to GetHeight_Obsolete. The new GetHeight simply uses GetLocationZ and combines it with a quick error check which was in the old version and as far as I know is different for GetLocationZ. Basically in my GetHeight function anything outside of the map was height 9999, as if there were a vertical wall at the end of the map. -GetHeight_Obsolete (This is how the original GetHeight function actually works.)This function takes in a location and returns a real which directly represents that location's terrain height. I'll start from the beggining since this is the easiest way for me to do it. Okay everything began with a conversation I had with one only known as Ari when he was telling me that he had come up with a way to read height in game. Well, lo and behold I got interested and he went on to explain to me how he extracted the w3e file from a map that he had and then using Zepirs tutorial figured out what meant what and realized basically that the whole w3e file was simply a list of points (in this case gridpoints) that represent the gridpoints that make up the terrain of any warcraft 3 map. He then went on about an explanataion of how it worked and some basic triggers which ingame found the nearest gridpoint to a unit and displayed that gridpoints height as the units height. Well this wasn't enough for me so I set out to do my own thing. Although I have to say without Ari's ideas I never would have had anything in the first place. And so I started by learning a little bit about w3e files, then some more about binary files, and poof came the w3e reader. A program which reads in the w3e and prints out a piece of code, which will stores the heights of every gridpoint on a map, into an array which can then be read. (This is the already known Initialize Height Variables trigger). Then I followed that up witht the GetHeigh function which takes in a location, reads the array, and pops out the exact height of the unit. Simple...yeah, damn I'm actually going to have to explain this now. Okay well we start off with a shitload of local variables, then a simple test to see if the location is actually inside the playable map area (if not it returns 9999 as the height indicating a giant wall) then what we do is we get the X coordinate of the location we were sent, and use that with a little rounding and dividing by 128 (the size of a tile) to figure out the x location (from 0 to 32 on a 32x32 map) of the grid box our location is in, then we repeat with y. Basically what we're doing is figuring out the top left corner of the grid box we are analysing and setting it's coordinates to tilex and tiley. Then we set xdist and ydist to remember how far away from the lower left corner of the gridbox our actual location is. Continuing on we simply use our tile information to extract from the array the proper values we need. (The array is an array of strings, where every 5 characters is another value). Then once we have the heights, we store the heights of each corner surrounding the gridbox that the location is in. Then the program simply takes the x slope of the left or right side and applies it to the xdist we stored before, and the y slope of the top or bottom side and applies it to the ydist we stored before to find out the exact height. (Top or Bottom and Left or Right sides are determined by whether the location is in the bottom left of the grid box or top right). -Sorry for the funky description but I lazied out because I saw I had plenty of comments within the code and you don't necessarily need to know this much about a function you most likely won't be changing. -GetslopeThe basics of the function are as follows, it inputs a location and outputs the slope of your movement if the "move" variable is set to true, or the slope of the angle you are facing if move is set to false. The function is pretty complicated and there's little reason to change it, if you're interested in the math simply look at the code. -CamZAdjustThis is a very crucial function which was necessary due to a smoothing technique that blizzard uses in everything they do, in this case it involved camera settings. Basically what was happening was that the height of the terrain was being smoothed into the camera height, so the camera was constantly off. To counteract this I created this function to adjust the height of the camera to accomodate for this. Basically it adjusts the Camera ZOFFSET not to the actual height, but to the different of height between the new position and the old one. Anyways it fixes the problem and that's all I really cared about. Initialization -Initialize VariablesAll very standard stuff, everythine that MoveCnt initializes is basically useless past movecnt[10] so you can erase it, but I didn't since I'm a lazy bum. Everything else is sortof self explanitory except for the custom jumpheight script. What that does is set whatever the inital height of the marine is as the sortof ground level comparison height that it uses to do all jump calculations. It's not important what the height is as long as it has a sortof anchor point from which to do all other calculations for jumping. -Initialize Height VariablesThis is just the initialization for the array that GetHeight and GetSlope use. Camera -Setup CameraJust some basic camera initailizations -FPV CameraFirst Person View camera settings -TPV CameraThird Person View camera settings Controls -Clear SelectionClears anything the player may accidently select while adventuring so you don't give out some random attack or more orders to your marine. -FireThe fire trigger is a bit complicated, the first thing to know is that it can be either run once or turned on for a periodic run machine gun style. The second, is that it's a linear trace that ends when the bullet is "underground", since any warcraft map is simply a warped plane made out of many gridpoints, it's sortof like a blanket that's been thrown over a few chairs, therefore if you ever go under the blanket, the only way to do it is to go through it which implies a collision, hence our collision detection system. Now the rest is simple, it takes the inital variables of location, facing, angle of attack + 5 (not sure why +5 but it fixes an innacuracy in firing that somehow appeared, this may have something to do with mapsize, I really never found out), and then it just loops until the height of the bullet is less than the height of the ground and then does a little impact. Now the important part comes in the itteration of movements, there are a few things that can be changed here to save up cpu ussage which is very precious specifically there's the polar projection (how far the unit moves every iteration) the modulo of i (how often it checks for surrounding units it might have hit) and the 10.0 * Tan(...) which you have to mach with the ammount in the polar projection. After that there's the simple checkhit function which scans around the bullet to check for targets and then checks the height of the target to make sure the bullet didn't go above or under them (assumes that 120 is the averge height of all things that can be fired at), then just does damage on impact sprays some blood or does a rifleimpact special effect if it hits ground. -FireGrenadeThis trigger is currently disabled and not working, it was supposed to shoot a grenade parabolically and impact just like a grenade would including bouncing off of walls. I stopped working on it about 80% of the way through because I couldn't make it perfect. -MoveCntReadThis function should be left alone, this is the function that constantly reads MoveCnt (the interface array, the one that the control program changes) and then accordingly runs functions changes variables or whatnot. It is also pretty well commented, so figure it out yourselves. -MovementsThis is the heart of the whole engine...well not really but still. Here is done everything that reacts to what MoveCnt does, the beggining code is written by Stoned but it basically runs all the mouse movement stuff and it's best to be left alone since it works and it works well. Now the rest is the fun part. First come the simple if's to run either the fpv or tpv cameras, then CamZAdjust is run to fix the rounding/smoothing problem. Then come some simple ifs to test if the right mouse button is down or the left mouse button and what weapon is selected for jumping and firing. Finally old mouse states are set to make sure you can't for instance hold the button down when firing a pistol. Console -This is all self explanitory text input stuffDebug -Self explanitory debug text display stuffMovement -JumpThis is a very important function that handles all the Z coordinate movements of the engine. It covers two things, air movement, and parting with the ground. Air movement is done easily enough by simply applying a constant gravity every second and then once again applying a changing ZVelocity to the units jumpheigh, which then accordingly changes the units fly height. It's all simple really =). I really don't want to explain this partially out of laziness but mostly because if you yourself can't figure it out, then you shouldn't be screwing with this function. And I will leave you with that. -Update PositionThis is the second heart of the engine, this is what applies all the xy velocity and friction and everything else changes. Although I won't be as much of a bastard as I was with the jump function, once again if you don't understand it yourself, don't screw with it, the global variables should be enough for you. As for the rest of you, first we start by calculating the x and y max velocities, this is used later. Then we have a quick check to make sure the player isn't standing still. If the player is moving, we then calculate x and y friction, and apply it positively or negatively depending on whether the speed is positive or negative. Repeat the same for y friction. Then we check if either of the frictions overran their limit and actually reversed the velocity from positive to negative, in which case we cut them off and set them to 0, then set the cutoff boolean to 0. Then we check if either the x or y was cut off and if not, we actually apply the friction to the velocity. Then we apply the maximums and cut off the velocities if the acceleration has placed them above the globally set maximums. Then we do a quick caluculation to make sure if the unit is on the ground and if it is we check to see if it isn't going up a slope that is too steep, if it is we set velocity to 0. And then finally after all this we apply the velocity to the actual position of the unit. -Foreward,Backward,Strafe Left,Strafe RightThis simple functions just use a little trigonometry to alter the x and y velocities properly applying the XYAccel that was globally set to represent what acceleration is applied if you hold down any of those keys. This is a re-post of my part of the original docmentation posted on the fps.wc3campaigns.net site. Attached is a slightly cleaned up version of the FPSMod Map, a few things were cleaned up, a few comments were added, and some things which should have been were disabled. |
| 03-17-2006, 03:21 AM | #2 |
I've started doing some work on FPS, although now that I look at it alot of the engine is more or less complete. I did some cleanup on the map and code that was needed as well as a mini-update for the new version of WoW. I'll probably be doing updates to the engine as well as taking requests for improvements/updates you would want, so feel free to post in this thread. |
| 03-18-2006, 02:36 PM | #3 |
Oooo sweet. Documentation back up. I'll sticky it once I can ^^ So let's see what problems I have since working with FPS Mod. 1st, Camera. I did this modification to CamZAdjust. I don't actually KNOW what the heck it does or what it is for, but after a lot of trail and error it seems to work. Basically, it allows for the camera to be constantly a certain height above the unit, and also it stops the camera from dropping sometimes when there is no designated FPSUnit[1]. For cinematics and stuff a lot of times somehow the camera will mysteriously slowly drop, so I added a boolean "Cinematic" to turn off and on this mysterious property. Code:
function CamZAdjust takes nothing returns nothing local real TrueHeight = GetHeight(GetUnitLoc(udg_FPSunit[1])) + udg_CameraHeight + GetUnitFlyHeight(udg_FPSunit[1]) set udg_TempCam = TrueHeight - GetCameraEyePositionZ() if ( udg_Cinematic == true ) then call SetCameraFieldForPlayer( Player(0), CAMERA_FIELD_ZOFFSET, GetCameraField( CAMERA_FIELD_ZOFFSET ) + udg_TempCam, 0.00 ) else call SetCameraFieldForPlayer( Player(0), CAMERA_FIELD_ZOFFSET, GetCameraField( CAMERA_FIELD_ZOFFSET ) + udg_TempCam, 0.01 ) endif endfunction Now I don't actually know wtf I am doing. Why does the camera constantly drop when you aren't focused on a unit, yet you need the value on the right to be 0.01 instead of 0.00 for the camera to work properly when a unit is locked on? It poses a few problems for making cinematics in an FPS Mod map, and I'm not sure if my solution is effective. 2nd, height. With the implementation of GetLocationZ(), is it neccessary to manually input the height terrain map? The problem is that for maps close to maximum size, one line of the height map will be too long to be contained and will overflow into the next line if the JASS window. Like "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" is too long to be contained in one line so the remaining a's will move on to the next line (at least I think it's too long to be contained in one line). This restricts map sizes. 3rd, Physics. I mostly just do away with most of the physics. I haven't been able to completely stop my character from sliding down slopes no matter how much I play with all the variables. Also, jumping is practically useless as I can't make attacks dodgable by jumping (not an engine concern) and walls can simply be walked up (this is an engine problem). By approaching a wall at a shallow angle, you can simply walk up it (and sometimes you can just walk straight up it). Pathing blockers won't work since the terrain is meant to be jumped on not a wall to completely stop you from moving. And that's all I can recall. I haven't worked with the FPS Engine for some time but I'll get back to it and try my best to see how it might possibly be improved. I haven't touched the code for firing much. |
| 03-19-2006, 01:29 PM | #4 |
1) I'll answer this a bit later when I have some time to take a look at it, just wanted to get a few quick answers in. I think you can make a cinematic equivalent of /fpv and /tpv which simply doesn't have an action at all, leaving the camera completely up to you as long as its in that mode. 2) It is no longer necessary to input a height map due to the use of GetLocationZ, although I'm still very proud of the GetHeight function, how it works, and the W3EReader. =P 3) I have currently disabled all the buggier pieces of the physics engine, specifically anything having to do with the slope function. You will no longer slide down hills, and you will no longer be blocked by steep hills (which only worked about half the time anyways). Also, cliffs suck. =/. I'm pretty sure pathing blockers would work if you used the crow form trick for fly height and made the unit flying when it jumped, would probably work. I'll probably try working with simpler and less realistic mechanics for path blocking, since a cliff being 45 degrees isn't very realistic anyways. =) |
| 03-19-2006, 03:41 PM | #5 |
BTW I've tried for a long time but I can't seem to get a true first person camera on uneven terrain. The camera height seems to be affected by the height of the terrain the camera is looking at as well, but I can't seem to remove it. e.g. If I'm walking up a hill the camera will be higher than it should be and if I'm walking down it shifts lower). I believe there's a function in the code that gets rid of this but I'm not sure what it is and how it's achieved. In other words, just setting Camera Height to GetLocationZ(point of FPUnit) isn't enough, what else needs to be done? |
| 03-19-2006, 10:27 PM | #6 |
It's nice to see you around still. I still check back myself from time to time. Unfortunately, I haven't gotten word back on the hosting, so no WIKI will be set up. :( |
| 03-19-2006, 10:52 PM | #7 |
Hey Ganon, I'm not actually checking back. I'm coming back. I havn't really checked back ever since I left, I'm now fully getting back into WC3 Jassing, and possibly all into FPSMod. |
| 03-20-2006, 05:19 AM | #8 |
Ant, I posted an entire Camera tutorial. It covers how the camera works in general, how it works in FPSMod, and how to accomdate for the Camera Z Values being wrong. To answer some of your other questions: The camera should never use the trigger camera lock thingy, all camera movement is handled by separate triggers, locking the camera onto the unit messes them up I think. The 0.00 and 0.01 values are durations. They represent how long it takes for the camera to change the value or pan the camera or whatever. I'll be doing a few more fixes on the map to fix how the camera works, this Camera tutorial I wrote has given me some good insight. Also, a quick answer to your cinematic troubles so you don't have to wait for my next version. In the Movements trigger (I think) where it calls the FPV or TPV trigger, create for yourself a CinematicCamera trigger with DoNothing and in the Movements trigger run that insead of FPV or TPV to prevent the camera from messing up your cinematics. |
