home *** CD-ROM | disk | FTP | other *** search
/ Hot Shareware 32 / hot34.iso / ficheros / VDUKE / TRYHACK.ZIP / Hackmap.txt < prev    next >
Text File  |  1998-06-01  |  56KB  |  471 lines

  1. ======================================================================
  2.  
  3.     HACKMAP - Version 1.0       June 1/98       by Karel Blaskovic
  4.  
  5. ======================================================================
  6. Copyright ⌐ 1998           Karel Blaskovic         All Rights Reserved
  7.  
  8.  
  9. TABLE OF CONTENTS:
  10.  
  11.      1) Introduction
  12.           a) Overview
  13.           b) What Hackmap is good for
  14.           c) What map versions Hackmap can edit
  15.           d) How Hackmap works
  16.  
  17.      2) Shareware and Ordering
  18.  
  19.      3) Support and Feedback
  20.  
  21.      4) Detailed Help
  22.           a) Getting started
  23.                   i)   Hackmap and Build
  24.                   ii)  Hackmap and Build Map Format
  25.                   iii) Values - types and limits
  26.                   iv)  Syntax used in Hackmap
  27.           b) Running Hackmap for the first time
  28.                   i)   Opening and Saving files
  29.                   ii)  The main screen
  30.                   iii) Looking around
  31.                   iv)  Online help
  32.           c) Changing values
  33.                   i)   Direct input in decimal
  34.                   ii)  Direct input in binary
  35.           d) Search and Replace fundamentals
  36.                   i)   Methods of searching
  37.                   ii)  Combinations of methods
  38.                   iii) Precautions
  39.                   iv)  Simple Search and Replace Examples
  40.           e) Search and Replace in depth
  41.                   i)   Using functions for Searching
  42.                   ii)  Using functions for Replacing
  43.                   iii) Examples using functions
  44.           f) Tips and Tricks
  45.                   i)   Copying Sectors
  46.           g) Reference
  47.                   i)   Hackmap Keyboard Commands
  48.                   ii)  Mathematical Functions, operators, constants
  49.                   iii) Internal Hackmap variables 
  50.                   iv)  Internal Hackmap functions
  51.                   v)   Element names in BUILD and HACKMAP
  52.                   vi)  A few facts about some numbers
  53.  
  54.  
  55.  
  56. 1) INTRODUCTION
  57.  
  58.     a) OVERVIEW
  59.  
  60.         HACKMAP is an MSDOS based MAP file editor for DUKE NUKEM 3D.  It was designed and created to assist in the production of top-quality DUKE3D levels.  HACKMAP is an extremely powerful tool that is intended to supplement the BUILD level-editor for the serious level builder as well the novice who wishes only to take advantage of a few important features or to save time while making levels.
  61.  
  62.     b) WHAT HACKMAP IS GOOD FOR
  63.  
  64.         Everything that isn't possible with Build, is possible with Hackmap.  MAP files are completely at your mercy!  Every aspect of every sector, wall, or sprite can be just viewed or altered.  Finally - a quick and easy way to change the "z-levels" of your sectors!  You can change one, some, or all values at a time making it a breeze to do things such as change shade or visibilities in the whole map, or change the wall tiles of a certain type to something else.  Because HACKMAP was intentionally designed to have as few limitations as possible, it is limited only by the DUKE3D map file format itself, not by the abilities of DUKE3D.EXE or BUILD.EXE.  One major advantage of this is that anything can be made to have any value as long as the MAP file can store the number.  This unique ability allows you to assign values that are not possible with BUILD but are valid nevertheless, and coming up with some designs that up until now could not exist.  You want a "curved" floor, or a window that is breakable only from one side?  HACKMAP allows you to do these things and much more: it "kicks butt" and that after all, is the whole idea behind DUKE3D!
  65.  
  66.     c) WHAT MAP VERSIONS HACKMAP CAN EDIT
  67.  
  68.         HACKMAP is not limited to any specific version of DUKE3D, as long as it uses mapfile version 7, which works with the regular version and the atomic edition, and any other version that may come out that has the ability to use the same maps.
  69.  
  70.     d) HOW HACKMAP WORKS
  71.  
  72.         HACKMAP is not a graphic editor such as BUILD but is instead a numeric editor.  Re-inventing BUILD.EXE would take longer to program, cost you more money, and would be for the most part, redundant and unnecessary.  Instead, focus was kept on versatility, practicality, and raw muscle.  It is fast and powerful yet very affordable.
  73.         HACKMAP allows you to deal with DUKE3D level data directly.  You can view the value of anything and everything, and can change the value of any piece of data that defines any aspect of any sector, wall, or sprite.  HACKMAP is essentially a binary file editor that is geared specifically for DUKE3D map files, making the data understandable in terms already known to a level maker who is familiar with BUILD.
  74.         Data can be changed individually, or "in bulk".  A special search-and-replace feature makes the process of finding what data to change relatively easy.  What is really amazing is that it allows you to apply virtually any function to any series of data elements.  If you have a series of walls and you want the shade to change gradually from light to dark, where each wall is 1 darker than the one before it, you can apply a function similar to "n+1" where "n" is the shade value of the previous wall.  In order to be able to do this, you are supplied with HACKMAP-specific variables which you can use in your functions.  For example, "select#" is a variable which is the "n'th" object found in a particular search.  (I refer to any individual sector, wall, or sprite as an "object" for lack of a better term.  For more information, see the instructions where it describes syntax).  There are also standard variables available such as PI, as well as a multitude of mathematical functions.  You can use these to do things like make smooth hills on a floor (eg: in the shape of a sine function), or make a ramp that becomes gradually steeper (eg: floors sloped according to a square function).  And, instead of taking hours, these things can be done in minutes.  Your imagination is the limit when it comes to replace-functions because any function is acceptable.  Using HACKMAP does not have to be as complicated as it may seem.  For the most part, it is very simple.  However, it does have the ability to do very complex things should some serious level-builders wish to make some awesome and unique maps.
  75.         Some data in DUKE3D MAP files is subdivided by DUKE3D.EXE and BUILD.EXE, according to the value of a particular bit.  For example, bit number 4 in the value of a wall's CSTAT determines whether or not the wall is masked or not.  In order to easily edit these CSTAT values, numbers can be viewed and edited in binary.  Best of all, there are also binary functions and binary operators. (eg: "&b", "and", "or", "xor").  This makes it easy to do things such as unmask all masked walls, or remove all one-way walls, or unblock all blocking walls.
  76.         A little bit of knowledge on the part of the user is a definite asset.  If you know how to use build, then you know most of what you need.  However, it is possible to assign values that are beyond acceptable limits of BUILD and DUKE3D, essentially "hacking" your level beyond recognition.  While some things, such as sector and wall shades, visibilities, and tile-numbers are fairly straight forward and easy to understand, others are not so straight forward.  BUILDHLP.TXT or BUILDHLP.EXE explain much that there is to know about DUKE3D map files but they do not explain everything.  I have in these instructions, made attempts to share what I have learned but it should be noted that even I do not know everything that there is to know about DUKE3D and its MAP files.  Some things remain to be learned.  For this reason I strongly suggest that map files are adequately backed up, especially if map files are being edited on an experimental basis.
  77.  
  78.  
  79. 2) SHAREWARE AND ORDERING
  80.  
  81.         HACKMAP is a shareware product.  (To view the license agreement please read README.TXT and ORDER.TXT)  You are free to use it to try it out.  However, you will not be able to save any changes.  This means that you will not be able to view the changes you have made in DUKE3D or BUILD except by viewing the number values in HACKMAP.  Unfortunately inconvenient, it was the only way to ensure adequate incentive to order the full version.  However, the sample MAPs are included with the shareware version to show the potential of HACKMAP.  How the sample maps were created is described step by step in section (3.d.iv) and (3.e.iii): examples of using search and replace.
  82.         At the present, HACKMAP is only available by cheque or money order.  Fill out the form in ORDER.TXT and when it is received you will be promptly mailed the full version in the manner you specify.
  83.         Since the order and the payment is to the author directly, and in light of many recent scams, for those who may have concerns I have provided personal information so that anyone may confirm my identity and sincerity should it be wished to do so.  For more information, see ORDER.TXT.
  84.  
  85.  
  86. 3) SUPPORT AND FEEDBACK
  87.  
  88.         Everyone who tries HACKMAP is encouraged to give any useful feedback or comments.  Improvements often only come with adequate feedback.  All of those who have ordered the full version are entitled to unlimited support for the period of a minimum of one year.  Furthermore, buying HACKMAP once entitles you to receive any future versions of HACKMAP at no cost!
  89.  
  90.  
  91. 4) DETAILED HELP
  92.  
  93.     a) GETTING STARTED
  94.  
  95.      i) HACKMAP AND BUILD
  96.  
  97.         HACKMAP is intended to work in conjunction with BUILD resulting in the need to switch from BUILD to HACKMAP and back to BUILD.  Unfortunately, there is no way around this but running both programs from Windows makes this switching back and forth much more convenient.
  98.  
  99.      ii) HACKMAP AND BUILD MAP FORMAT
  100.  
  101.         HACKMAP, since it deals directly with MAP files, has everything to do with the BUILD MAP FORMAT.  A copy of the BUILD MAP FORMAT is included in BUILDHLP.TXT or BUILDHLP.EXE.  Although described with the assumption that the reader has an inherent understanding of either C or C++, the information illustrated is nevertheless useful for everyone because it describes the meaning of each element.  For example, it states that "wallptr" is the "index to first wall of sector".  This value is changed in BUILD by pointing the mouse cursor on a floor near a wall and pressing <ALT-F>.  BUILD describes this as the "first wall" and is important for sloping floors and ceilings, and panning textures.  HACKMAP uses the same names as those described in the BUILD MAP FORMAT, except for some minor alterations.  Not only are the same names used, but the order is the same as in the BUILD MAP FORMAT.  A convenient conversion table is included in the reference section of this text.
  102.  
  103.  
  104.      iii) VALUES - TYPES AND LIMITS
  105.  
  106.         A value can be any number provided that it does not exceed limits determined by the organization of the MAP file itself, except for any x, y, and z, value which has a HACKMAP induced limit.  The limit for these is 99999999 which was introduced for display purposes but leaves a more than adequate possible value range.  The actual limit for all elements can be seen by loading LIMITS.MAP into HACKMAP.  LIMITS.MAP is a dummy MAP for this purpose only and should not be loaded into BUILD or DUKE3D.  As mentioned previously, having the ablility to  replace values to their absolute limits does not mean that any number is acceptable to BUILD and DUKE3D.  This was done intentionally.  You should generally not run into problems because you will have a specific value to change to already in mind.  Experimenting with values however, may cause unpredictable behavior or errors while running BUILD and DUKE3D and so this should always be kept in mind.
  107.         Values have different types, meaning that they can be signed or unsigned.  The reason for this is that computers can cope with 0's and 1's but cannot directly cope with negative numbers and their "-" signs.  Internally, a negative number is defined by the most significant bit of a binary number.  If that bit is a "1", it is a negative number.  Without getting into the method of binary computations, it may be helpful to note that since both signed and unsigned numbers can have a "1" as the most significant bit, any negative number can be also interpreted as a positive number depending on what you take the most significant bit to mean.  For example, one-byte binary number &b11111111, if unsigned, has the value of 255, but if it is viewed as a signed number, the value is (2^8 - 255) = 256 - 255 = -1.  The reason for stating this is that you may at some point in time while using HACKMAP, encounter numbers that don't seem right.  For example, you may be changing the value for one kind of element in binary to &b1111111111111111, and may be having the number -1 appear in the box showing the decimal value.  For a different kind of element, the same binary number &b1111111111111111, may show up as 65535.  This is not an error.  The difference is that the first element is a signed value and the second is an unsigned value, but both are stored as the same binary number.
  108.  
  109.      iv) SYNTAX USED IN HACKMAP
  110.  
  111.         There was a need to come up with a generic name for sectors, walls, and sprites.  For this, the term "object" was given.  "Object" is an individual sector, wall, or sprite.  As a collective, they are given the name "type".  For example, a level that has 100 sectors and 200 walls, has 100 objects of the type "sectors", and 200 objects of the type "walls".  Also, each object has values associated with it that define its position in the level, the tile it uses, the shade, etc.  HACKMAP uses the generic term "element" for these.  For example, the tile number used as the mask on the masked wall numbered 20, in HACKMAP would be the "overpicnum" element of object numbered 20 of type "walls".
  112.         It should be noted that objects are numbered starting from 0.  This means that the first object is numbered 0, the eleventh is numbered 10, etc.  Both the BUILD MAP FORMAT and HACKMAP state the number of objects and those are natural numbers (starting at 1).  The highest sector number, for example in a map that has 220 sectors (numsectors=220), would be 219.
  113.  
  114.  
  115.     b) RUNNING HACKMAP FOR THE FIRST TIME
  116.  
  117.      i) OPENING AND SAVING FILES
  118.  
  119.         The first thing that HACKMAP requires you to do is open a MAP file to view or edit.  Especially during your initial trial, make sure you back up any MAP file you intend to use.  No online help is available for the open-file routine but standard keys of <TAB>, <ENTER>, and arrow keys are to be used.  While in the open-file routine, <ESC> will always cause the execution of the program to be terminated.  At other times, <ESC> causes you to go back to where you were before.  Using <ESC> is the only way to open a different file while HACKMAP is running.  Saving files is accomplished by pressing <F3> when available.  At some times, such as in the middle of a search, <F3> is not available.  However, whenever there has been a change made to file and you quit using <Q>, or you want to open a different file, HACKMAP will prompt you and ask if you wish to save the current file.  Once again, files are saved only with the full version of HACKMAP.
  120.  
  121.      ii) THE MAIN SCREEN
  122.  
  123.         After opening a MAP file, the main screen is displayed.  To open a different file, <ESC> opens the open-file window.  On the top of the main screen, the basic map information is displayed and this information, like all values displayed in HACKMAP, are in decimal unless specified as binary.  This data on the top of the main screen is the information that is not specific to any object.  It included the MAP version, starting coordinates, the starting sector, and the number of objects of each type.  These values cannot be altered with HACKMAP.  Use BUILD to change the start position of Duke, and to add and delete objects.
  124.         The lower section displays the current values of all elements for a given object.  There are 23 elements for every sector and sprite, and 17 elements for every wall.  When you first start HACKMAP, the main screen displays the elements for sector numbered 0.
  125.         While in BUILD, much of this information is available to you in 2D mode: for sectors by positioning the mouse cursor on the desired sector and pressing <TAB>, for walls by positioning the mouse cursor near the desired wall (on the correct side if it is a 2-sided wall) until it is flashing and pressing <ALT-T> and then <ENTER>, and for sprites by positioning the mouse cursor near the desired sprite until it is flashing and pressing <ALT-T> and then <ENTER>.  However, this information does not use the same names as described in the BUILD MAP FORMAT or the names used in HACKMAP.  Although quite easy to figure out, a conversion table is provided in the reference section.
  126.  
  127.      iii) LOOKING AROUND
  128.  
  129.         The type of object can be changed by pressing: <ALT-1> for sectors, <ALT-2> for walls, and <ALT-3> for sprites.  Once the desired type is selected, objects can be flipped through sequentially by using the <+> and <-> keys.  You can jump to a particular object by pressing <J>, typing the number of the object (objects remember are numbered from 0) and pressing <ENTER>.  When you first start HACKMAP, the element cursor is not visible but is displayed the first time you press any arrow key.  The cursor changes position only with the arrow keys and during a search or search and replace.  It does not change position when loading a different MAP file.  This allows for easy comparison of the value of an element between MAPs.
  130.  
  131.      iv) ONLINE HELP
  132.  
  133.         <F1> and <F2> are the help keys.  They are available most of the time.  <F1> shows the meaning of the function keys in HACKMAP as well as a quick reference to the recognized functions and symbols in HACKMAP.  <F2> displays any keys that are available for use as input at the given time.  The specific function of these keys is described in the reference section of this text file.
  134.  
  135.  
  136.     c) CHANGING VALUES
  137.  
  138.      i) DIRECT INPUT IN DECIMAL
  139.  
  140.         The value of any element of any object can be changed by direct input in decimal.  Only values that are highlighted by the element cursor can be changed.  The arrow keys move the cursor around.  One the correct element is selected, pressing <ENTER> will cause an additional display to appear below the list of elements and their values.  To change a value, type in the number and press <ENTER>.  Other keys such as <DEL> and <BCKSPC> and arrow keys can also be used and a complete listing can be found in the reference section.  Keep in mind that the limits for HACKMAP may be beyond acceptable limits of BUILD and DUKE3D.  For more information read the section "Values - types and limits".
  141.  
  142.      ii) DIRECT INPUT IN BINARY
  143.  
  144.         Most values can also be changed by direct input in binary but it should only be desirable to do so for the CSTAT values where each bit of a binary number has a separate function (see the BUILD MAP FORMAT).  Instead of typing the number in decimal, press <TAB>.  <TAB> toggles between input in decimal and input in binary.  Use <0>, <1>, and <spacebar> to change the bits.
  145.  
  146.  
  147.     d) SEARCH AND REPLACE FUNDAMENTALS
  148.  
  149.      i) METHODS OF SEARCHING
  150.  
  151.         The <F5> key brings up the Search and Replace window.  The up and down Arrow keys select which item is highlighted and the spacebar or Enter selects the item.  A search works internally in the following order: type, object, element, value of the element.  In other words, HACKMAP looks to the right type, then the right object, and then the right element, and then for a particular value or range of values (or bit pattern).  Selecting "All" types, "All" objects, "All" elements, and "ALL" values, will simply move the element cursor to the next element in the MAP file.  This is the basis for all searches but more specific searches limit this pattern when you alter the settings in the Search and Replace window.  Search limits for values, objects, and the types can be narrowed down so that you can find anything you are looking for. The keys that can be used at any time during the setting of the parameters can be seen by pressing <F2> and are listed in the reference section of this text.  Once the correct search and replace parameters are set, pressing <F5> initiates the search.  Without "auto-replace" selected, the search will pause when it finds a matching value.  At this time it is possible to enter manually any value.  When <Enter> is pressed the search continues.  If you are search and replacing and come up to a value that you do not want to have altered, you may press the spacebar instead of <Enter>.  <ESC> cancels the search.  It is possible to turn the auto-replace on and off during a search and replace.  The <P> key does this.  It is recommended that until you become familiar with HACKMAP, you do not select "auto-replace" to start with.  Instead, start without it and once you are sure that your search and replace is doing what you wanted it to do, then hit <P> to initiate the auto-replace.  At the end of every search, some statistics are displayed.  If the search is canceled, the statistics that are displayed may not add up perfectly; typically, details of what was unchanged may show one less than the total number unchanged.
  152.  
  153.      ii) COMBINATIONS OF METHODS
  154.  
  155.         It is possible to set some interesting and useful combinations.  You can search for a range of values and a particular bit pattern.  This is somewhat redundant since you can determine the values by a more specific bit pattern, but it is nevertheless allowed.  Another valid combination is searching for objects with a function and a range.  This will cause a search to find objects according to the specified function as long as it is within the specified range.
  156.  
  157.      iii) PRECAUTIONS
  158.  
  159.         There is a small snag to watch for when searching for objects by function.  It is possible to choose a function that will result in an endless search loop.  If this happens, check the function and the range of objects.  Use of functions is described better in (4.e.iii) examples.
  160.  
  161.      iv) SIMPLE SEARCH AND REPLACE EXAMPLES
  162.  
  163.         Example #1:
  164.         Suppose you wanted to find all wall picnums (tile numbers) that range from 650 to 655 in the given MAP file, you'd set the type to "walls only", objects to "All", elements to "Specific" and then choose element number 7 which is "picnum", and finally would set the values parameter to "Range" and type in the range from value (650) and the range to value (655).  If you also wanted to replace these, select "and replace" and then choose a value.
  165.  
  166.         Example #2:
  167.         If you wanted to search for a particular bit, for example a "1" in the bit #0 position, because you wanted to find all blocking walls, the parameters would be set as: type "Walls only", Objects "All", Elements "Specific" - "cstat", Values "Select bits" - "...............1".  In the "select bits" parameter, you may have a "0","1" or a period.  Having either a "0" or "1" means that in order for a value to be found, the particular bit must be what is specified.  A period means that either a "0" or "1" in that bit position is acceptable for the element value to be found.
  168.  
  169.  
  170.     e) SEARCH AND REPLACE IN DEPTH
  171.  
  172.      i) USING FUNCTIONS FOR SEARCHING
  173.  
  174.         Only the object number searched can be searched for using a function.  If you had a series of 50 walls which were numbered 0,1,2...49 and wanted to search for a value only in the even-numbered walls excluding wall #0, you could select the "objects" - "specific" parameters and manually type the numbers of the walls you wanted: 2,4,6,...48.  To save time, you could use a function.  There is often more than one way to specify a function because there are different internal variable that can be used.  The internal variable "select#" is an index to the "n'th" object found.  The function "select#*2" (which actually means "next object to be found = (select#*2)" is what you could use.  "select#" always equals 1 when a search starts.  To find the first matching object, the value of "select#" is substituted into the equation and is then calculated.  So we have: (1)*2 which equals 2.  The first object found will be object #2.  When the search continues, "select#" is incremented by one and is now equal to 2.  The second element found would be: (2)*2 = 4.  "select#" would then be again incremented and we would have: (3)*2 = 6, and this process would continue until there are no objects left to find.
  175.         There is another way to find all even numbered objects excluding #0, by using a function using "object#".  "object#" is substituted by the current object number displayed when a search continues.  In order to start at object #2, you would have to ensure that object #0 is displayed in the main screen before pressing <F5> and bringing up the search and replace window.  Assuming this is the case, and you type "object#+2" as your function, the following is what would take place:  The current object is object #0, (0)+2 = 2.  "object#" now equals 2.  For the second find, (2)+2 = 4.  "object#" now equals 4 and so we'd arrive at the third by calculating (4)+2 = 6.
  176.  
  177.      ii) USING FUNCTIONS FOR REPLACING
  178.  
  179.         Using functions for replacing is the same idea as using them for searching.  The important difference is that replace functions are applied to determine the replacing value, rather than the object found.  Suppose we start with our 50 walls (#0 to #49) and want to make each wall darker than the one before it by 1.  Again, we could do this more than one way.  The easiest is to use the function "object#+1".  During the search and replace, "object#" is substituted, the function is calculated, and the calculated value is the replacing value for the element or elements selected, in this case we would have selected the "shade" element.  Replacing functions have access to a greater number of internal variables, a list of which is provided in the reference section of this text.  Replacing functions can be as complex as you like, producing some very interesting results.  The examples included in the following section describes the process that was involved in making the three sample maps: SAMPLE1A.MAP, SAMPLE1B.MAP, and SAMPLE1C.MAP.
  180.  
  181.      iii) EXAMPLES OF USING FUNCTIONS
  182.  
  183.         The Making of SAMPLE1A.MAP, SAMPLE1B.MAP, SAMPLE1C.MAP:
  184.         This example is explained in detail and may seem complicated at first.  Once you become familiar with HACKMAP, using functions, and know the necessary pieces of information about DUKE3D MAPs, things go much faster and easier.  SAMPLE1C.MAP took me about five minutes to make from SAMPLE1B.MAP.  Three of those five were spent coming up with the function to use!
  185.  
  186.         Step #1)   The first step involved in making SAMPLE1A.MAP involved the use of BUILD.  A simple narrow sector with 4 walls was made.  To make things easier, the floor was raised so that the z-level = 0.  The ceiling was also raised.  Also to make things easier, wall #0 was made to be the "firstwall".  Then, using the mouse and the right <ALT> key, this sector was copied and the copy placed beside the original turning wall #2 (opposite the "firstwall") into a red 2-way wall. These two sectors were copied and placed in a similar adjacent fashion creating a total of 4 sector.  The process was repeated a few more times until a there was a total of 128 sectors (#0 to #127).  To have a look at the sector and wall numbering that BUILD had assigned our sectors and walls, we used <ALT> and <ALT-T><ENTER>.  Sectors run in a line and are numbered #0 to #127.  The walls of sector #0 are numbered #0 to #3, the walls of sector #1 are numbered #4 to #7.  We see then that the walls along the top are numbered #1,#5,#9 and so on, and the walls on the bottom are numbered #2,#6,#10 and so on.  This map was then saved as SAMPLE1A.MAP
  187.         Step #2)   When this was complete we switched to HACKMAP and we decided to change the tiles of the floor and ceilings.  After pressing <F5> we selected the following parameters:  "and replace", values: "all", elements: "specific" - "ceilpicnum", objects "all", type "sectors only",replace: value: 241.  Making sure the setting are correct, we initiated the search and replace with <F5>.  With a few presses of <Enter> and checking to make sure what was happening is what we desired, we switched to auto by pressing <P>.  When the search and replace finished, we now had tile #241 on all of our ceilings.
  188.         Step #3)   In a similar fashion, we then changed all the floortiles to tile#372.  Then we changed the ceiling shade to 12 and the floor shade to 13.  These were done with the exact same parameters in the search and replace with the exception that the specific element and replacing value were different.
  189.         Step #4)   For the walls, in the main screen we pressed <ALT-2> and then <F5>.  We want the far left and far right wall to have a picnum (tile number) of 241.  Out of all the top-to-bottom running walls, only these two are visible because the others are two-way walls so we can feel free to change the picnums of all walls running in a top-to-bottom direction to tile number 241.  The top-to-bottom walls are numbered #0,#2,#4,#6...etc.  Our search and replace had the following parameters: "and replace", Values: "all", elements: "specific"+"picnum", objects: "use Function" - "(select#-1)*2", type: "walls only", replace: value: 241.
  190.         Step #5)   Now we repeat the process for left-to-right walls: the walls along the top and bottom.  These walls are numbered #1,#3,#5,...etc.  For these we selected tile #435.  Using the same parameters except for the right selection for the element, and using the object search function "select#*2-1" and a replace value of 435, is how this was achieved.
  191.         Step #6)   To make things interesting, we decided to change the tile of every left-to-right wall in sector #0,#16,#32...etc.  Those walls are numbered #1,#65,#129,#193...etc.  We know this because the top wall of sector #0 is wall#1, the top wall of sector #1 is wall #5, the top wall of sector #3 is wall #9 and so on.  The top wall is always equal to the (sector number)*4+1.  We do a search and replace and we have the following parameters: "and replace", values: "all", elements: "specific"+"picnum", objects: "use Function"+"select#*64+1", type: "walls only", and a replace value of 705 which is the number of the tile corresponding to a wall light.  We then do the exact same thing for the walls along the bottom (#3,#67,#131,#195,...etc) with the object function "select#*64+3".  This map we now saved as SAMPLE1B.MAP.
  192.         Step #7)   Now comes the hard part - making the floor in the shape of wave.  For this we decide to use a function of sine because we know that the graph of the sine function looks like a wave.  What else do we know?  The sine of 0 is 0, sine of 90 degrees is 1, sine of 180 degrees is 0, and the sine of 270 degrees is -1.  The sine of anything always results in a value between 0 and 1.  We also know that using <PGUP> in BUILD on a floor causes the z-value of the floor to change by 1024.  Also, the higher the floor, the lower the z-value (which is somewhat backwards but that's the way it is).  If we want the height of our wave on the floor to range between 8192 and -8192 (remember our floor was set to have a z-value of 0 to start), which is the equivalent of 8 <PGUP>'s and 8 <PGDN>'s at the highest and lowest part of the wave respectively, we need to multiply a simple sine function which produces values between -1 and 1 by 8192.  We also want four full waves on our floor.  One wave in the standard sine function is from 0 to 360 degrees.  Four waves therefore, are from 0 to 360*4 which is 0 to 1440.  We have 128 sectors. 1440 degrees divided by 128 sectors is 11.25 degrees per sector.  We now have enough information to come up with a replace function.  The new z-value of our floor will be:
  193.         int(sin(rad(object#*11.25))*8192).  
  194. We would analyze this equation like this:  "object#" is substituted by the current object number. (we must make sure we start at 0 before opening the search window with <F5> - or we could use "(select#-1)" which would bring the same result and we we not have to be sure of this)  We want the sine of the (object number)*11.25 since we wanted to jump 11.25 degrees for every sector.  before taking the sine though, we convert degrees to radians with the rad() function.  After taking the sine (which produces values from -1 to 1) we multiply our factor of 8192.  To eliminate any decimal values produced, we put the whole thing into an int() function which rounds any value down to the first integer value lower than the original value.  Our search and replace parameters would then be "and replace", values: "all", elements: "specific"+"floorz", objects "all", replace: "use Function" + "int(sin(rad(object#*11.25))*8192)".  If we had a look at our map now, we we would see that the levels of our floors are overall in the shape of a wave but are not sloped - we have a series of steps going up and down in the shape of a sine wave.
  195.         Step #8)  Finally we must take care of the slope of each step.  It is not stated specifically anywhere in the manual for BUILD, but slope values can be reached by taking the height difference between one sector and the next sector (rise) and dividing it by the length of the floor (run) and multiplying by 256. In BUILD, using the <[> or the <]> keys can make slopes but these keys change the slope value of a floor or ceiling in increments of 512.  However, DUKE3D.EXE will accept in-between values.  HACKMAP can change values to basically anything.  To change the slopes on the floors, we must come up with a replace function.  We need to come up with specific values for our rise and run so we can calculate the slope.  Our run is the width of our sectors.  That width is 256.  We know this because of the size of grid used in BUILD, and we know it for sure if we calculate it by the position of the walls.  The x and y coordinates of walls specify the position of the left end of the wall.  The left side of Wall #1 in our map connects with the left side of sector #0.  The right side of sector #0 is also the left side of sector #1 which has the same x coordinate as wall #5 because wall #5 is the top wall of sector #1.  So we take the x coordinate of wall #1 and subtract from the x coordinate of wall #1 and we get: (26880)-(26624) = 256.  As for the required "rise", we must use the same equation we used to change the height of the floor.  The height of the first sector (sector #0) was:
  196. int(sin(rad(object#*11.25))*8192)
  197. and the height of the second (sector #1) was: int(sin(rad((object#+1)*11.25))*8192)  --(assuming object# remained constant).
  198. The difference in height between those two sectors then is:
  199. int(sin(rad((object#+1)*11.25))*8192 - int(sin(rad(object#*11.25))*8192
  200. and that difference is used in the calculation of the slope of object#.  Putting all these bit of information together we can come up with our complete replace function which is:
  201. int([int(sin(rad((object#+1)*11.25))*8192) - int(sin(rad(object#*11.25))*8192)]/[256]*256)
  202. The rise and run can be seen in the square brackets.  Since we are dividing by 256 and then multiplying by 256, the equation can be simplified down to just:
  203. int[int(sin(rad((object#+1)*11.25))*8192) - int(sin(rad(object#*11.25))*8192)]
  204. Our parameters are then: "and replace", values "all", elements "specific" + "floorhieghtnum", objects "all", type "sectors only", replace: "use function" + "int[int(sin(rad((object#+1)*11.25))*8192) - int(sin(rad(object#*11.25))*8192)]".  After having performed this search and replace, one small detail is left.  In order for DUKE3D to slope any floors, bit#1 of the floor's "stat" element must be a "1".  One last search and replace with the following parameters is necessary:  "and replace", values: "all", elements: "specific"+"floorstat", objects "all", type: "sectors only", replace: "use Function" - "elemx or &b000000000000010.  This replace function takes whatever the current value of the current element is (elemx), and performs a bitwise "or" function with the binary number shown.  This places a "1" in bit position 1 and does not change the value of any other bit.  In the case of this sample map, all floors had a floorstat value of 0 to begin with and we could have replaced by value, with the value 2 which is "10" in binary (which ="000000000000010").  The MAP file was then saved as SAMPLE1C.MAP, and we now have a wave on a floor unlike anything anyone has ever seen in DUKE3D!
  205.  
  206.  
  207.     f) TIPS AND TRICKS
  208.  
  209.      i) COPYING SECTORS
  210.  
  211.         As you use HACKMAP more and more, it will become apparent just how much time it can save.  One of the best uses for HACKMAP deals with its ability to easily change the z-levels of sector floors and ceilings as well as the z-coord of sprites.  Here's how to take advantage of this: Any sector or group of sectors that you use often (like doors, doors with frames, etc) does not need to be re-made or, copied and fitted painstakingly.  With HACKMAP you can make a library MAP file that store things until you wish to copy them.  If you think you will be using a particular door often, copy it to the library MAP.  Once there, use HACKMAP to change the z-values of all sector floors, ceilings and sprites.  Change them so that the floor of the lowest sector is at a particular level, perhaps -500000 or some other uncommon number that is not likely to be found in anywhere in anyone's map.  As you copy more things to this library MAP, you can select the right sectors to change z-levels by search and replacing only those that have a value greater than -500000.  When you want to reuse something such as a door with its frame, copy it to the MAP of your choice with BUILD.  Then use HACKMAP to alter the z-level.  You can select what z-coordinates to change by search and replacing only those values that are less than or equal to -500000, and you can replace it to any z-level you want.  By doing this you are essentially using the levels -500000 and above as a "buffer area" used to contain things in the process of copying (remember - the higher the floor, the lower its z-coordinate).  For example, a simple drop-down door is found in a level and you want to be able to re-use it.  The floor is at 30000 and the ceiling is at 20000.  Copy it to your template MAP.  Do a search using the value range -499999 to 999999.  Use the function "elemx+(-500000-(+30000))" or simply "elemx-530000".  That will make the elements you specify ("floorz" and "ceilingz" for sectors, "z-coord" for sprites) to decrease in value by 530000.  Your sector floor will then be at -500000, and your ceiling will be at -510000 and any sprites will be somewhere in between.  When you want to copy it to a new map, copy it using BUILD, and then change the z-levels accordingly with HACKMAP.  If you wanted the floor of your copied door to end up at -32000, then you would search for values less than or equal to -500000 and would use the replace function "elemx-(-500000-(-32000))" or simply "elemx+468000" for all elements that define a z position of any kind.  Even better is if you move the sectors and sprites to your library so that the significant parts of the sector or group of sectors is at a certain level, rather that simply the lowest sector floor.  By significant parts, I mean those that will end up joining other sectors when you finish copying them.  If this method is chosen, and your buffer-zone starts at -500000, you'd want to place your significant part at a level such as -600000 so that even floors extending below the significant part's z-level have a value below -500000.  By doing this you will save hours and hours of unnecessary and monotonous work and can spend the extra time using your imagination inventing new things!
  212.  
  213.  
  214.     f) REFERENCE
  215.  
  216.      i) HACKMAP KEYBOARD COMMANDS
  217.  
  218.         Open File:    
  219.           <TAB>           - selects filename, files, directories, OK,
  220.                             and CANCEL
  221.           arrow keys      - moves cursor in filename, or selects 
  222.                             particular file or directory
  223.           <ENTER>         - opens the currently displayed file
  224.           <ESC>           - opens nothing and exits HACKMAP
  225.           other keys      - <DEL>, <BCKSPC>
  226.  
  227.         Main Screen:
  228.           <ALT-1>         - view sector data
  229.           <ALT-2>         - view wall data
  230.           <ALT-3>         - view sprite data
  231.           <+> & <->       - view next or previous object
  232.           <PGUP> & <PGDN> - same as <+> and <->
  233.           <J>             - jump to object # ?
  234.           arrow keys      - move element pointer
  235.           <ENTER>         - change element value
  236.           <F1>            - help : general
  237.           <F2>            - help : display valid keystrokes
  238.           <F3>            - save file as
  239.           <F5>            - search (and replace)
  240.           <ESC>           - go back and open another MAP file
  241.           <Q>             - exit HACKMAP
  242.  
  243.         Change Element Value:
  244.           <0> to <9>      - types digit
  245.           <->             - make value negative
  246.           <TAB>           - toggles input in decimal and binary
  247.           <ENTER>         - enters the new value of the element
  248.           <DEL>           - changes value display to zero
  249.           <BCKSPC>        - same as <DEL>
  250.           left arrow      - moves cursor left
  251.           right arrow     - moves cursor right in binary input mode
  252.           <SPACEBAR>      - skip element without changes during a
  253.                               search and replace or selects a "." in the
  254.                               current bit position during binary input
  255.           <P>             - turns auto-replace on and off during a
  256.                               search and replace
  257.           <ESC>           - back to main screen or 
  258.                               cancel search and replace
  259.           other keys      - <F1> <F2> <F3> <Q>
  260.  
  261.         Search and Replace:
  262.           up & down arrow - move position of highlighted item
  263.           <TAB>           - same as down arrow
  264.           <SPACEBAR>      - mark the highlighted item 
  265.           <ENTER>         - same as spacebar
  266.           right arrow     - for some items, if they were selected
  267.                               previously, will do the same thing as
  268.                               the <spacebar> with the difference that
  269.                               previously input values are kept
  270.           <F5>            - initiates the search, or search and replace
  271.           other keys      - <F2> <ESC> <Q>
  272.  
  273.           -after pressing <ENTER> or <SPACEBAR> some items require more
  274.             input.  Common keys are: <ENTER>, numbers and letters, right
  275.             arrow, <DEL>, <BACKSPACE>, <ESC>
  276.           -during "object: specific" selection, if no objects were
  277.             previously selected, the only valid keys are <ESC> and right
  278.             arrow. If right arrow is pressed, selection of specific
  279.             objects can be typed in.  <ENTER> enters the object number
  280.             and continues with another.  To finish the sequence use the
  281.             <ESC> key. At this time you may use the up and down arrow
  282.             keys to check your inputs, use <DEL> to remove any undesired
  283.             inputs, right arrow to amend an input, and <ENTER> and the
  284.             very end to finish or <ESC> to cancel.
  285.  
  286.      ii) MATHEMATICAL FUNCTIONS AND OPERATORS
  287.  
  288.         * The characters "~", "a", "b" signify numeric expressions
  289.         * The character "#" signifies a string of 0's and 1's (binary)
  290.  
  291. Function:    Syntax:                Result:
  292. -----------------------------------------------------------------------
  293.  INT   |  int~ or int(~)    |   -rounds ~ down to next lowest
  294.        |                    |     integer value
  295.  ABS   |  abs~    abs(~)    |   -returns the absolute value of ~
  296.  SGN   |  sgn~    sgn(~)    |   -returns -1,0, or 1 depending if
  297.        |                    |     ~ is negative,0, or positive
  298.  SIN   |  sin~    sin(~)    |   -returns the sine of ~
  299.  COS   |  cos~    cos(~)    |   -returns the cosine of ~
  300.  TAN   |  tan~    tan(~)    |   -returns the tangent of ~
  301.  ASN   |  asn~    asn(~)    |   -returns the inverse sine of ~
  302.  ACS   |  acs~    acs(~)    |   -returns the inverse cosine of ~
  303.  ATN   |  atn~    atn(~)    |   -returns the inverse tangent of ~
  304.  LOG10 |  log10~  log10(~)  |   -returns the log, base 10, of ~
  305.  LOG2  |  log2~   log2(~)   |   -returns the log, base 2, of ~
  306.  LOG   |  log~    log(~)    |   -returns the natural log (ln) of~
  307.  FACT  |  fact~   fact(~)   |   -returns the factorial of ~
  308.  MOD   |  amodb   (a)mod(b) |   -returns the modulus: the
  309.        |                    |     remainder after a is divided by b
  310.  DEG   |  deg~    deg(~)    |   -converts from degrees to radians
  311.  RAD   |  rad~    rad(~)    |   -converts from radians to degrees
  312.  &b    |  &b#               |   -converts # to decimal
  313.  ¬  |  ¬#             |   -converts # to decimal after
  314.        |                    |     switching all 0's to 1's and
  315.        |                    |     switching all 1's to 0's
  316.  ----------------------------------------------------------------------
  317.         Other:
  318.  ----------------------------------------------------------------------
  319.  ()[]{}|                    |    -any of these brackets are valid
  320.  ^     |                    |    -exponentiation symbol
  321.  *  /  |                    |    -multipy and divide
  322.  +  -  |                    |    -add and substract
  323.  and   |  aandb   (a)and(b) |    -performs bitwise "and" between two
  324.        |                    |     decimal numbers.  decimal numbers
  325.        |                    |     are automatically converted to 
  326.        |                    |     binary and then back to decimal
  327.  or    |  aorb    (a)or(b)  |    -performs bitwise "or"
  328.  xor   |  axorb   (a)xor(b) |    -performs bitwise "xor"
  329.  pi    |                    |    -returns 3.14159265358979
  330.  rnd   |                    |    -returns random number between 0 and 1
  331.  ----------------------------------------------------------------------
  332.  
  333.         * When using functions, some lead signs in some combinations
  334.           are not valid:  (ie ...*-2/.... must be ....*(-2)/...)
  335.  
  336.  
  337.      iii) INTERNAL HACKMAP VARIABLES
  338.  
  339.  Variable: | Availability:   |            Meaning:
  340.  -----------------------------------------------------------------------
  341.            |Object | Replace |
  342.            |Search |         |
  343.  -----------------------------------------------------------------------
  344.  elemx     |   -   |   yes   | -the value that is highlighted at any
  345.            |       |         |   time by the element value pointer
  346.  elem(~)   |   -   |   yes   | -the value of an element in the current
  347.            |       |         |   object. Elements are indexed by number.
  348.  bitmask   |   -   |   yes   | -is the binary string of digits that was
  349.            |       |         |   last defined by value:"select bits".
  350.            |       |         |   Any "." are replaced with "0"
  351.  !bitmask  |   -   |   yes   | -is the same as using ¬bitmask.  It is
  352.            |       |         |   the bitmask with the 0's replaced with
  353.            |       |         |   1's and the 1's replaced with 0's
  354.  object#   |  yes  |   yes   | -the value that is equal to the current
  355.            |       |         |   object number.
  356.  select#   |  yes  |   yes   | -the value that is equal to the "n'th"
  357.            |       |         |   object being searched for.  It always
  358.            |       |         |   starts at 1 and increments by one
  359.            |       |         |   after the next matching object is found
  360.            |       |         |   and optionally replaced.
  361.  tfound#   |  yes  |   yes   | -the total number of elements found
  362.  found#    |  yes  |   yes   | -the number of elements found in the 
  363.            |       |         |   current objects. It is never < 1.
  364.  -----------------------------------------------------------------------
  365.  
  366.         * examples: 1) if wall #2 is the current object, elem(9) would
  367.                        be equal to the the wall's "shade".  Index 
  368.                        numbers start at 1 and go to 23 for sectors and
  369.                        sprites and range from 1 to 17 for walls.
  370.                     2) if a value: "select bits" was chosen, and
  371.                        "....0..1.1..001" was entered,
  372.                        "000000010100001" would be the "bitmask" and
  373.                        "111111101011110" would be the "!bitmask"
  374.  
  375.                        
  376.      iv) INTERNAL HACKMAP FUNCTIONS
  377.  
  378.         Internal HACKMAP functions are input in the same place as object search functions.  This is mostly only for convenience.  Internal HACKMAP functions do not behave like other functions.  They are essentially "pre-search" aids.  The two HACKMAP internal functions are: WALLS(~) and SPRITES(~).  These functions automatically pre-select the wall numbers or sprite numbers of the walls and sprites of the given sector "~".  For example, suppose that in a MAP,  sector #4 has 4 walls that are numbered #67,#68,#74,#76 .  Typing WALLS(4) after selecting objects: "use Function" will cause two things to happen.  Objects: "specific" will be marked instead of objects:"use Function", and the numbers 67,68,74,76 will be entered as specific selections as if you had typed them in yourself.  The display for objects:"specific" will show the value of the first wall, in this case it will show "1)  Wall # 67".  SPRITES(~) works in the exact same way as WALLS(~).  The presearch with SPRITES(~) takes longer than WALLS because there is no index to the sprites in the sector data and must actually be searched for.  WALLS(~) systematically finds the right walls by checking the "wallptr" value of the sector and subsequently the "point2" values of the walls.
  379.  
  380.  
  381.      v) ELEMENT NAMES IN BUILD AND HACKMAP 
  382.  
  383.  ----------------------------------------------------------------------
  384.  BUILD MAP FORMAT   |    HACKMAP         |    BUILD
  385.  ----------------------------------------------------------------------
  386.  SECTORS:
  387.  ----------------------------------------------------------------------
  388.  wallptr            |  wallptr           |  Firstwall
  389.  wallnum            |  wallnum           |  Numberofwalls
  390.  ceilingz           |  ceilingz          |  Z-coordinate
  391.  floorz             |  floorz            |  Z-coordinate
  392.  ceilingstat        |  ceilstat          |  Flags (hex)
  393.  floorstat          |  floorstat         |  Flags (hex)
  394.  ceilingpicnum      |  ceilpicnum        |  Tile number
  395.  ceilingheinum      |  ceilheinum        |  Ceiling heinum
  396.  ceilingshade       |  ceilshade         |  Shade byte
  397.  ceilingpal         |  ceilpal           |  Palookup number
  398.  ceilingxpanning    |  ceilxpan          |  
  399.  ceilingypanning    |  ceilypan          |
  400.  floorpicnum        |  floorpicnum       |  Tile number
  401.  floorheinum        |  floorheinum       |  Floor heinum
  402.  floorshade         |  floorshade        |  Shade byte
  403.  floorpal           |  floorpal          |  Palookup number
  404.  floorxpanning      |  floorxpan         |  
  405.  floorypanning      |  floorypan         |
  406.  visibility         |  visibility        |  Visibility
  407.  filler             |  filler            |
  408.  lotag              |  lotag             |  lotag (and Tags)
  409.  hitag              |  hitag             |  hitag (and Tags)
  410.  extra              |  extra             |  Extra
  411.  ----------------------------------------------------------------------
  412.  WALLS
  413.  ----------------------------------------------------------------------
  414.  x                  |  x-coord           |  X-coordinate
  415.  y                  |  y-coord           |  X-coordinate
  416.  point2             |  point2            |  Point2
  417.  nextwall           |  nextwall          |  nextwall
  418.  nextsector         |  nextsector        |  nextsector
  419.  cstat              |  cstat             |  Flags (hex)
  420.  picnum             |  picnum            |  Tile number
  421.  overpicnum         |  overpicnum        |  OverTile number
  422.  shade              |  shade             |  Shade
  423.  pal                |  pal               |  Pal
  424.  xrepeat            |  xrepeat           |  (X,Y) repeat
  425.  yrepeat            |  yrepeat           |  (X,Y) repeat
  426.  xpanning           |  xpanning          |  (X,Y) pan
  427.  ypanning           |  ypanning          |  (X,Y) pan
  428.  lotag              |  lotag             |  lotag (and Tags)
  429.  hitag              |  hitag             |  hitag (and Tags)
  430.  extra              |  extra             |  Extra
  431.  ----------------------------------------------------------------------
  432.  SPRITES
  433.  ----------------------------------------------------------------------
  434.  x                  |  x-coord           |  X-coordinate
  435.  y                  |  y-coord           |  Y-coordinate
  436.  z                  |  z-coord           |  Z-coordinate
  437.  cstat              |  cstat             |  Flags (hex)
  438.  picnum             |  picnum            |  Tile number
  439.  shade              |  shade             |  Shade
  440.  pal                |  pal               |  Pal
  441.  clipdist           |  clipdist          |  Clipdist
  442.  filler             |  filler            |  
  443.  xrepeat            |  xrepeat           |  (X,Y) repeat
  444.  yrepeat            |  yrepeat           |  (X,Y) repeat
  445.  xoffset            |  xoffset           |  (X,Y) offset
  446.  yoffset            |  yoffset           |  (X,Y) offset
  447.  sectnum            |  sectnum           |  Sectnum
  448.  statnum            |  statnum           |  Statnum
  449.  ang                |  angle             |  Angle
  450.  owner              |  owner             |  Owner
  451.  xvel               |  xvel              |  X-Velocity
  452.  yvel               |  yvel              |  Y-Velocity
  453.  zvel               |  xvel              |  Z-Velocity
  454.  lotag              |  lotag             |  lotag (and Tags)
  455.  hitag              |  hitag             |  hitag (and Tags)
  456.  extra              |  extra             |  Extra
  457.  ----------------------------------------------------------------------
  458.  
  459.  
  460.      vi) A FEW FACTS ABOUT SOME NUMBERS
  461.  
  462.         -Build automatically adjusts the xrepeat and yrepeat, as well as the xpanning and ypanning when walls are created.  The exact method is unknown to me.
  463.         -It is not possible to change only the "wallptr" of a sector without re-numbering the walls in the sector.  Swapping objects easily is not possible in HACKMAP version 1.0.  Anything that may require the "firstwall" of a sector to be in a particular place should be done in BUILD with <ALT-F> before switching to HACKMAP.  This will always be required when dealing with sloped floors and ceilings since they always slope from the "firstwall".
  464.         -Some elements such as "shade" can have negative values but have the same effect in Duke3D and BUILD as a value of zero.  This can be made use of if you want to temporarily brighten you MAP so that it is easier to work with.  You can, with a search and replace, with a replace function, change all the shades by subtracting a constant from the original value (eg "elemx - 50").  This has the same effect as changing all shades to zero (assuming that there were no shades darker than 50).  To change back to the original, use the inverse function of what you used to in the first place (eg "elemx + 50").
  465.         -I have tried to change the values of some elements for sprites in the hopes of being able to make sprites which are moving when DUKE3D first starts the level.  I don't know if it is possible.  If it is, I sure would like to know about it!
  466.  
  467.  
  468.                           HAPPY HACKING !!!
  469. =======================================================================
  470.  
  471.