PNG Loading, Coordinate Based Worldmap System for ROM MUDs, v1.1, April 16, 2025
----------------------------------------------------------------------------------------------------------

License / Conditions of Use:
* All applicable licenses that this is being installed in much be followed.
* The code headers in worldmap.c & worldmap.h must not be removed or altered.  If the code is moved
  to another file, the headers may be moved to the files using the bulk of the code.  If functions
  such as the room_movement or wmap_movement are moved to something like act_move.c, there is no need
  to duplicate the headers if they are still present in worldmap.c.
* If the LodePNG library is used, the headers in lodepng.c and lodepng.h must not be removed.
  -If one were to rework the code to use libpng or another PNG library, this term is not applicable
   provided that the lodepng files are removed.
* Some form of credit or acknowledgement must be placed in an in-game helpfile accessible to everyone.
  Suggested helpfiles would be something for the worldmap system, a helpfile used to list snippets or
  code contributors, or a credits helpfile (or the credits command).
  -Preferred text for credit is as follows:
   Worldmap by Joseph Benfield (Hades_Kane/Diablos of End of Time & StockMUD)
      and Matt Fillinger (Grieffels of End of Time & When Worlds Collide)
* The system was developed in near total isolation from elements of codebases it was written in, but
  very small elements of Diku/Merc/ROM code remain.  If used as is, the license terms for those codebases
  must be followed.  It is our belief that removal of any of the existing code that was, after the fact,
  ported to the system would release any user of the code provided in worldmap.c and worldmap.h from those
  specific obligations if being used in a different codebase.  We make no guarantee toward that belief.
  The following functions in worldmap.c use code from Diku/Merc/ROM:
  bool can_leave, bool can_enter, void follow_me, void room_movement, and bool can_move_points.
  Code in other parts of the source, especially the OLC WEdit code, is directly derived from ROM code.
* There is no limitation on redistribution of this system if significant modifications are made, or if
  included in a wider codebase or derivative release, provided that all conditions of use are met with
  the new release, that credit to the original authors remains in place, and that it is not used in a
  commercial product or project that directly generates revenue of any kind.
* This code / software is provided 'as-is', without any express or implied warranty.  In no event will the
  authors be held liable for any damages arising from the use of this software.


Suggested Helpfile for WEdit:
----------------------------------------------------------------------------------------------------------

Syntax: wedit
        show | reload | done
        tile <create|delete|save>
        sector <type> | sector fill <type> | sector walk <type>
        sector circle/square/fractal <type> <distance> <true|false>
        symbol <X>
        name <text>
        desc (enters into append mode)
        visibility <#>
        passable <yes/true | no/false>
        exit <vnum|save|delete>
        wlist tiles [all] | wlist exits
        reset [all|wmap#] | reset [modify|mob|obj|delete]>
        save <wmap|tile|exits>
 
WEDIT is a command and editor for altering the worldmap system, and behaves as
much like the other OLC editing commands as possible.
 
SHOW, or hitting return on a blank line, will display the details of the "tile"
including coords, visibility distance, passable status, custom symbol, name,
and description.  RELOAD will refresh the map from whatever state the PNG is
saved.  DONE will exit WEdit.
 
TILE handles the creation, deletion, or saving of custom tile values.  Note
that a symbol, name, or description must be present for a tile to save.
 
SECTOR handles the terrain of the tile.  Any valid sector may be supplied as an
argument and it will modify the in-memory map and (if saved) the PNG from which
the map loads.  SECTOR WALK will make every movement automatically apply the
specified sector type.  FILL will perform a flood fill, which will apply the
sector to all tiles within a given boundary.  CIRCLE, SQUARE, and FRACTAL will
create an area of sector, sized based on the distance value.  The optional true
or false value will adjust for font height with circle/square, and will use a
decay algorithm with fractal that makes the outer edges more sparse.
 
SYMBOL sets a custom symbol to replace the sector based symbol.  Only use a
single character (along with whatever desired color code).
 
NAME and DESC work like any other OLC editor.  Sets the tile's name and desc
as though you were editing a room.
 
VISIBILITY sets how far away the tile will appear on the scan command.
 
PASSABLE determines whether a character may pass onto or out of the tile.
 
EXIT handles creating and designating a tile as the entry point to a normal
area.  To create the corresponding exit from an area to the map, simply create
a one way exit from the area to the vnum of the map.  The exit from the map to
the area must be present, otherwise you'll need to fake it with an mprog.
 
WLIST TILES will show all of the tiles on the current wmap.  The optional ALL
parameter will show the tiles for every map.  WLIST EXITS will show the exits
for the current wmap.
 
RESET handles the addition, deletion, and display of tile based resets.  The
command with no argument will display the resets in the room.  ALL will show
the resets for the current wmap, while supplying a specific map number will
list those.  MODIFY will swap a mob or obj reset for another vnum.  DELETE will
delete the reset, and if it is a mob that has objs reset on it, it will clear
those as well.  The other commands mirrors normal OLC resets as much as
possible, using this pattern of syntax:
  reset <mob|obj> <vnum> [max] [x][y][z]
  reset obj <vnum> on <mob_vnum> <wear|hold> [max]
The max and coordinate values are optional, and default to "1" and the current
coordinates, respectively.  In this context, max represents how many of the
reset will load over the course of the map repopping/resetting.
 
SAVE WMAP saves the PNG file of the current wmap, SAVE TILE will save the
custom tile data of the current wmap, and SAVE EXITS will save the exits file
for all wmaps.  ASAVE WMAP may also be used to save all wmap data for the
current wmap and all wmap exits.


Installation Instructions:
----------------------------------------------------------------------------------------------------------

It is highly advised that you back up your code and areas before attempting installation of this code.  It
does involve having to make game-wide changes/updates to your area files by adding in certain code, saving
all areas, then adding in additional code, in a very specific order.  Any error in this process will make
your areas not load and cause a huge headache to correct.  It's easier to restore a backup of area files
and try again in such an instance.

This code was written specifically for installation in ROM based MUDs.  It is adaptable to other codebases
but not without some headache.  It has been developed and tested, specifically, for the "QuickMUD" release
of ROM, and was originally developed for use in Grieffel's "When Worlds Collide" project and the StockMUD+
project by Diablos, Grieffels, and others.  A live, working example of the map system can be experienced
in StockMUD+, accessible at stockmud.com, port 5001.  These instructions will follow installation in a
stock ROM/QuickMUD release and involve changes in approximately 36 of the 57 files, largely due to the
fact that every single loop in the code that checks for ->people or ->contents has to have a check for
coordinates, and nearly every char_to_room and obj_to_room requires coordinate setting functionality.  The
final step (10) in the installation before going through the specific saving/loading routines to properly
update area files will involve crawling through the files for these, but earlier steps will involve
setting some of this code to avoid having to come back to the same files repeatedly.

The system uses a series of #define configuration options located at the top of worldmap.h that allows for
ease of customization for certain aspects of the system.  Detailed explanations for those will be provided
but note that for the options you do choose to use, you may simply delete those defines and alter the code
where those are called to suit your preferences and reduce bloat in the code.

Provided in the system are multiple options for world map PNGs.  You are welcome to use any of those
however you please, with no restrictions on copyright, redistribution, or whatever.  You will need to name
those according to however you choose to have them listed in the wmap table, but this will be revisited
in Step 3.  If you are using a largely stock ROM world and wish to incorporate the stock world into this
system, the map labeled "thera.png" is designed to accommodate that world.  Additionally, the wmap_exits
file and thera tile dat file are included which contain the from-map to-area exit links to the stock areas
and the tiles with custom ASCII art to represent many of the areas that are linked directly along with the
name/description/visibility data to work with the scan command / screenreader options.  You will still
need to unlink the areas from one another and create a one way exit from the area to the map, which is
detailed in step 2.

In some parts, the code may include framework for additional expansion.  While the system is fully
functional as-is and as intended, it is also intended to be a base for other, interested game Admins to
be able to expand to suit their games specific needs.  While not used in any functional manner in the
system, framework has been provided for a Z axis coordinate.  This was done largely to avoid having to
enact a system wide reworking in the event that one wanted to use a Z axis.  The mapgrids do not account
for a Z axis as that would be unnecessary memory usage when the system does not actively use Z.  On End of
Time, the Z axis was used as means to "fake" additional levels of the map, predominately for use in the
submarine system, where a certain water sector allowed for submerging into an underwater map that was
derived by alternate symbols and mechanics for certain sectors.  This system does not include such
functionality, but this is mentioned as an example of how certain aspects could be adapted for other uses.
The system also includes placeholder framework for screen reader compatibility.  If you have any sort of
check for screen reader use, a configuration option, or anything in your game, find the places that have
a "bool screenread" and that would be the appropriate place to check for that.  What is included may not
be the most elegant solution, but it is a functional attempt.

Note that in the vast majority of Diku derived codebases, the method by which new lines and returns are
handled and ordered do not follow telnet standard protocol.  This code uses the correct return / newline
format (\r\n as opposed to the incorrect \n\r).  While this may be inconsistent with your existing code,
it should cause no conflict or problems.

The installation instructions will also provide for optional command structures for interaction with the
map that bypasses the WEdit system, just incase your game doesn't have OLC or you just simply don't want
to install that functionality.  Additionally, it is recommended that if you have "wiznet" functionality,
you add a "bugs" option so that any bug calls are visible to the Admins.  This will make debugging not
only this system far easier, but is highly useful as a general debugging tool, especially for mobprogs and
the like.  If you aren't interested in installing wiznet bug calls, you can skip to "Step 2".

Step 1: Bug Calls in Wiznet
-------
In merc.h, find the wiznet flags (WIZ_ON for example) and add this in the next available spot:
#define WIZ_BUGS                (U)

In const.c, add to the wiznet table (const struct wiznet_type wiznet_table[]):
    {"bugs", WIZ_BUGS, L1},

In db.c, add to the bug command (void bug (const char *str, int param)) just above log_string:
    wiznet( buf,NULL,NULL,WIZ_BUGS,0,0);


Step 2: Create worldmap area, vnums, and map directory.
------
Decide how many maps your game will be using and create a new area file with at least as many vnums as
maps.  I would recommend allocating at least 100 vnums per map, for things like map based objects and mobs
to be contained within the map area(s).  You can make each map have its own area if you wish, rather than
containing them in a single area.  It makes no difference for the operation of the code.  Create a room
for each map you will be using and make note of those vnums and which map they are for.  In your MUD
directory, alongside other files such as ../src/, ../area/, etc. create a new directory named "maps".
Place your desired PNG files for your maps in this directory, and take note of their filename.  After the
system is fully installed, in order to link areas to the map, you must first create an exit from the map
to the area (if you are using the Thera files, this step will already be done provided you have all of the
areas that comes with stock ROM).  After which, the entrance/exit of your area to the map, you will create
a one way exit ('south room <vnum' for example) to the vnum of the map you are linking to.


Step 3:  worldmap.c, worldmap.h
-------
If needed, add worldmap.c to your makefile.  There are several values at the top of worldmap.h that you
will need to edit or comment in/out to suit your preferences, or to define values specific for your MUD.

CONFIGURATION DEFINES are optional values to customize how the map behaves.  Note that in most instances,
the use of HOLYLIGHT bypasses a lot of restrictions placed on players by these defines.  For the values
that have 16/256 options, the 256 option should only be enabled if you are using expanded 256 color codes.
Even if you are using 256, you may still opt for the 16 color version for aesthetics or performance.  Also
note this snippet assumes the 256 color codes in the format of KaVir's protocol snippet (ie: {[F123]) and
that said snippet does not include grayscale colors.  The code needed to add grayscale to the system is
included in its own file.

-WMAP_SECT_MOBS - mobs not flagged "sentinel" will wander the map.  If this define is present (not
  commented out) then mobs will stay within whatever sector type they are presently in.  Useful for
  making sure any goblins loaded in a specific forest will only wander within it, for example.
-WMAP_SECT_MOVE - based on the movement value of a sector type, when present this will make travel over
  certain sectors slower.  Field allows for fast movement, while forests, mountains, etc. are slower.
-WMAP_SECT_VIS - based on movement value, this will make the map radius view smaller when in higher value
  sectors and reduce the distance at which the player will see others when they use scan.
-WMAP_SECT_HIDE - based on movement value of the sector that another character is in, this will restrict
  the distance at which a player will see the other's worldmap icon indicator and their presence on scan.
-WMAP_WTHR_VIS - based on weather conditions, this will reduce a player's map radius and scan distance.
-WMAP_NIGHT_VIS - based on day/night, this will reduce a player's map radius and scan distance.
-WMAP_MOVE_PTS - this makes movement points deduction and restriction active on the worldmap.
-WMAP_SHOW_OBJS - objects will display on the worldmap like other characters
-WMAP_NIGHT_FADE16 - night time will dim worldmap sector colors
-WMAP_NIGHT_FADE2516 - night time will dim worldmap sector colors, only enable if using 256 colors.
Note that these options will slow down how quick the map draws, specially SECT_DEPTH256:
-WMAP_WATER_DEPTH16 - water sectors will have color depth
-WMAP_WATER_DEPTH256 - water sectors will have color depth, only enable if using 256 colors.
-WMAP_SECT_DEPTH256 - non water sectors will have color depth, only enable if using 256 colors.
-WMAP_LIGHTS16 - lights worn by players will brighten map at night, NIGHT_FADE must be set.
-WMAP_LIGHTS256 - lights worn by players will brighten map at night, NIGHT_FADE must be set, only enable
  if using 256 colors.
-WMAP_OBJ_LIGHTS - glowing obj lights will brighten map at night, must have WMAP_LIGHTS defined.

MUD SPECIFIC VALUES are things that need updating according to your specific game, such as size of maps,
number of maps, and their vnums.
-WMAP_ONE/TWO/THREE/etc - these are vnum defines that should match the room vnums you created in Step 2.
  You may rename these defines to whatever you wish, but you will need to adjust these in the wmap_table.
-MAX_WMAP - this value should match however many maps you are using.  As maps are added, this value should
  be increased.
-MAX_WMAP_SCAN - this value defines how far the default value of scan will be.  Adjust as desired.
-STAFF_DISPLAY - when holylight is on, this determines how big of a radius staff will see.

For your convenience, the wmap_table and new sector_flags table are located at the top of worldmap.c.
Whether you are using any of the provided maps or creating new maps, you will need to update the
wmap_table.  If you changed the name of your vnum defines in worldmap.h, that wiill be the value you alter
under MAP VNUM.  MAP NAME is entirely your discretion, as this does not effect the operation of the
system.  Whatever you have named your PNGs for the maps must be reflected in this table.  The X value
will match the width of your PNG, and the Y value will match the width.  WRAPPING is an option as to
whether navigation and visually your map will "wrap" around past its edge.  TRUE creates a round world
and FALSE creates a flat one.  DISPLAY SIZE is the default map radius for players.

Later in the instructions, you will be commenting out or deleting the existing sector tables, but you will
need to update/add to this table for any sectors your game has that isn't represented in the table.  Note
that any sectors listed here other than INSIDE, CITY, and AIR are represented in the provided PNGs.
It is also worth noting that DEEP_WATER and ROUGH_WATER are only listed for aesthetic purposes on the PNG,
but that on End of Time, those additional sectors have been used to restrict boat travel, and to define
regions where underwater ocean is explorable.  There is no harm in removing these sectors, but you will
need to update the provided PNGs accordingly if you are using any of them, and alter the bool IS_WATER()
function.

The NAME and BIT values should match what is in your existing sector flags table located in tables.c.
The MV column represents movement cost which is currently in act_move.c's movement_loss array.  The R G B
values represent the RGB pixel value of the PNG.  For example, in the PNG whenever a pixel is 0, 132, 0,
then that pixel represents the FIELD sector and the code translates that when reading the file.  The
values listed are default values and match the provided PNGs.  You may change these to suit your
preferences, but the PNGs will need to be adjusted accordingly.  The "3x3wal" and "3x3flr" values are
included as both EoT and WWC make use of Midboss's "Detailed, 3x3 display ASCII automapper for ROM MUDs",
and that has been rewritten to draw from this table instead of having yet another table to update when new
sectors are added.  There is no harm in leaving these values if you are not using asciimap.c, but you may
remove these with no harm to the operation of the system if you wish to remove bloat.  The MAPSYMB value
represents what each sector will display on the worldmap view.  You should only use a single character
along with your color code.  If you are using any expanded, 256 color code, you may use expanded colors
with this system, but note that the more information you are sending through the mapper, the less optiimal
it will perform.  Sending dozens of {[F050] is sending a lot more data than {G.  Note that the mapper and
system does include code to reduce redundant color codes.  Lastly, PASSMSG works to both define whether a
character may pass over a sector type (NULL if so), and if not, what message is displayed when attempting.

Other considerations:
-void follow_me() has a movement echoed commented out, if you'd prefer for it to echo to the player.  It
  also assumes the presence of AFF_CHARM in your game.
-bool can_leave() also assumes AFF_CHARM.
-bool can_enter() assumes the stock ROM clan code with guild rooms and such.
-void room_movement() is largely stock move_char broken into its own function to reduce code redundancy,
  but it includes a "doorbump" feature that will be included as part of the system.  If you are not
  interested in including this feature, feel free to edit/omit that part of the code.  This also assumes
  AFF_CHARM along with ROOM_LAW and ACT_AGGRESSIVE flags.
-bool can_move_points() breaks the movement point check and deduction into it's own function, and assumes
  the AFF_FLYING, AFF_HASTE, and AFF_SLOW flags.
-const char *wmap_symbol() is where you would change the character map indicators.
-add_border_row() and draw_wmap() has the code for the map borders and is where you would edit to change
  the look, if desired.  If altered, do the same in do_zoomwmap().
-int get_wear_location() may need updating if you have added or removed any wear slots in your game.
-void do_zoomwmap() is provided as a utility command, but could easily be adapted for use in things like a
  farsight spell, or similar situational based mechanic.  It could also be used as a baseline for tying
  into the Z axis framework, with the zoomed_grid being loaded when needed and being what is displayed to
  a character instead of the regular map, with the zoom level and coordinate setting on movement being
  based on the value of the Z axis.


Step 4: merc.h
-------
-struct    char_data:  add this near the bottom:
    //worldmap.c
    sh_int             wmap[4]; //wmap index, x, y, z
    sh_int             reset_wmap[4]; //wmap index, x, y, z

-struct    pc_data:  add this with the other ints:
    int                wmap_sec;    //worldmap.c
  and this with the other sh_ints:
    sh_int            doorbump[2]; //bump exits repeatedly to unlock/open... [0] = direction, [1] = count   //worldmap.c

-struct    obj_index_data: with the other ints:
    int                 value[7]; //worldmap.c

-struct    obj_data: with the other ints:
    int                 value [7]; //worldmap.c
and this with the other sh_ints:
    //worldmap.c
    sh_int              wmap[4]; //wmap index, x, y, z
    sh_int              reset_wmap[4]; //wmap index, x, y, z

-find the function prototypes section, specifically effect.c and change them to this:
void    acid_effect    args( (CHAR_DATA *ch, void *vo, int level, int dam, int target) ); //worldmap.c
void    cold_effect    args( (CHAR_DATA *ch, void *vo, int level, int dam, int target) ); //worldmap.c
void    fire_effect    args( (CHAR_DATA *ch, void *vo, int level, int dam, int target) ); //worldmap.c
void    poison_effect  args( (CHAR_DATA *ch, void *vo, int level, int dam, int target) ); //worldmap.c
void    shock_effect   args( (CHAR_DATA *ch, void *vo, int level, int dam, int target) ); //worldmap.c

-scroll down a little to handler.c and add these:
void    WAIT_STATE            args( ( CHAR_DATA *ch, int npulse ) );
void    DAZE_STATE            args( ( CHAR_DATA *ch, int npulse ) );

-find the Character macros section, where IS_NPC is defined, add:
#define IS_HOLYLIGHT(ch)    (!IS_NPC(ch) && IS_SET(ch->act,PLR_HOLYLIGHT))

-in the same section, either comment out or delete #define WAIT_STATE and #define DAZE_STATE


The rest of what goes in merc.h CAN be simpled placed at the bottom, but I will include where the logical
placement would otherwise be.


*****This would normally go with utility macros, under CHECK_POS*****

//worldmap.c
#define CREATE(result, type, number)                                           \
do                                                                             \
{                                                                              \
    if (!((result) = (type *) calloc ((number), sizeof(type))))                \
    {                                                                          \
        perror("malloc failure");                                                  \
        fprintf(stderr, "Malloc failure @ %s:%d\n", __FILE__, __LINE__ );          \
        abort();                                                                   \
    }                                                                          \
} while(0)
//worldmap.c
#define LINK(link, first, last, next, prev)                                    \
    do                                                                         \
    {                                                                          \
        if (!(first))                                                          \
        {                                                                      \
            (first) = (link);                                                  \
            (last) = (link);                                                   \
        }                                                                      \
        else                                                                   \
            (last)->next = (link);                                             \
        (link)->next = NULL;                                                   \
        if ((first) == (link))                                                 \
            (link)->prev = NULL;                                               \
        else                                                                   \
            (link)->prev = (last);                                             \
        (last) = (link);                                                       \
    } while (0)
//worldmap.c
#define UNLINK(link, first, last, next, prev)                                  \
    do                                                                         \
    {                                                                          \
        if (!(link)->prev)                                                     \
        {                                                                      \
            (first) = (link)->next;                                            \
            if ((first))                                                       \
                (first)->prev = NULL;                                          \
        }                                                                      \
        else                                                                   \
        {                                                                      \
            (link)->prev->next = (link)->next;                                 \
        }                                                                      \
        if (!(link)->next)                                                     \
        {                                                                      \
            (last) = (link)->prev;                                             \
            if ((last))                                                        \
                (last)->next = NULL;                                           \
        }                                                                      \
        else                                                                   \
        {                                                                      \
            (link)->next->prev = (link)->prev;                                 \
        }                                                                      \
    } while (0)


*****Find #define DIR_DOWN and place this under*****
//worldmap.c
#define DIR_NORTHEAST    6
#define DIR_SOUTHEAST    7
#define DIR_SOUTHWEST    8
#define DIR_NORTHWEST    9


*****Find #define SECT_MAX and put these above them.  Update your numbers here, and SECT_MAX accordingly*****

//worldmap.c
#define SECT_ROCK_MOUNTAIN 11
#define SECT_SNOW_MOUNTAIN 12
#define SECT_BEACH         13
#define SECT_DEEP_WATER    14
#define SECT_ROUGH_WATER   15
#define SECT_TRAIL         16
#define SECT_ROAD          17
#define SECT_SWAMP         18


*****Find the global constants section (liq_type, group_type, etc.):

//worldmap.c
extern    const    struct    sec_type      sector_flags[SECT_MAX];


*****find the room type section (struct    room_index_data) and this can go under that*****
*****if you are not using asciimap.c and want to remove extra code as mentioned above with the sector table
     this is where you would remove "char *  wall;" and "char *  floor;"                              *****

//worldmap.c
struct sec_type
{
    char *  name;
    char *  desc;
    int     bit;
    int     move;
    int     red;
    int     green;
    int     blue;
    char *  wall;
    char *  floor;
    char *  wmap_symb;
    char *  pass;
};


*****the function prototypes section, where you changed the effects.c and added to handler.c*****

/* worldmap.c */
bool same_room args((CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *obj));
int wmap_vnum args((CHAR_DATA *ch, OBJ_DATA *obj));
int wmap_x args((CHAR_DATA *ch, OBJ_DATA *obj));
int wmap_y args((CHAR_DATA *ch, OBJ_DATA *obj));
int wmap_z args((CHAR_DATA *ch, OBJ_DATA *obj));
int wmap_num args((CHAR_DATA *ch, OBJ_DATA *obj));
int wmap_vnum_index args((int vnum));
bool is_wmap_vnum args((int vnum));
bool is_wmap args((CHAR_DATA *ch, OBJ_DATA *obj));
void set_x args((CHAR_DATA *ch, OBJ_DATA *obj, int value));
void set_y args((CHAR_DATA *ch, OBJ_DATA *obj, int value));
void set_z args((CHAR_DATA *ch, OBJ_DATA *obj, int value));
void set_wmap args((CHAR_DATA *ch, OBJ_DATA *obj, int value));
void set_coords args((CHAR_DATA *ch, OBJ_DATA *obj, int x, int y));
void clone_coords args((CHAR_DATA *tch, OBJ_DATA *tobj, CHAR_DATA *sch, OBJ_DATA *sobj));
int wmax_y args((CHAR_DATA *ch));
int wmax_x args((CHAR_DATA *ch));
char *wmap_name args((CHAR_DATA *ch, OBJ_DATA *obj));
void process_wmap_resets args((void));
int get_sector args((CHAR_DATA *ch, int wmap_index, int x, int y));


Step 5: interp.c and interp.h
-------
-In the command table (const struct cmd_type cmd_table), add this under "down":
    //worldmap.c
    {"northeast", do_northeast, POS_STANDING, 0, LOG_NEVER, 0},
    {"ne",        do_northeast, POS_STANDING, 0, LOG_NEVER, 0},
    {"northwest", do_northwest, POS_STANDING, 0, LOG_NEVER, 0},
    {"nw",        do_northwest, POS_STANDING, 0, LOG_NEVER, 0},
    {"southeast", do_southeast, POS_STANDING, 0, LOG_NEVER, 0},
    {"se",        do_southeast, POS_STANDING, 0, LOG_NEVER, 0},
    {"southwest", do_southwest, POS_STANDING, 0, LOG_NEVER, 0},
    {"sw",        do_southwest, POS_STANDING, 0, LOG_NEVER, 0},

-At the bottom under the OLC commands, and change L6 to whatever level you want these commands restricted:
    //worldmap.c
    {"showsectors",  do_show_sectors, POS_DEAD, L6, 1},
    {"wmaptable", do_wmaptable, POS_DEAD, L6, 1},
    {"wedit", do_wedit, POS_DEAD, L6, LOG_NORMAL, 1},
    {"wmapshow", do_wmap_show, POS_DEAD, L6, LOG_NORMAL, 1},
    {"zoomwmap", do_zoomwmap, POS_DEAD, L6, LOG_NORMAL, 1},

In interp.h, these can all go together at the bottom, or if you alphabetize your list, place them
accordingly:

//worldmap.c
DECLARE_DO_FUN( do_northeast    );
DECLARE_DO_FUN( do_northwest    );
DECLARE_DO_FUN( do_southeast    );
DECLARE_DO_FUN( do_southwest    );
DECLARE_DO_FUN( do_savemap      );
DECLARE_DO_FUN( do_show_sectors );
DECLARE_DO_FUN( do_wmaptable    );
DECLARE_DO_FUN( do_wedit        );
DECLARE_DO_FUN( do_wmap_show    );
DECLARE_DO_FUN( do_zoomwmap     );


Step 6: Adding WEdit: olc.c, olc.h, olc_act.c, olc_save.c
-------

-In olc.c, add the include for worldmap.h:
#include "worldmap.h" //worldmap.c

-olc.c, in bool run_olc_editor(), add:
        case ED_WMAP: //worldmap.c
            wedit (d->character, d->incomm);
            break;

-olc.c, in char *olc_ed_name(), add:
        case ED_WMAP: //worldmap.c
            sprintf (buf, "WEdit");
            break;

-olc.c, in char *olc_ed_vnum(), add:
        case ED_WMAP: //worldmap.c
            tile = find_wmap_tile(wmap_num(ch,NULL),wmap_x(ch,NULL),wmap_y(ch,NULL),wmap_z(ch,NULL));
            sprintf (buf, "%s", is_wmap(ch,NULL) ? wmap_name(ch,NULL) : "");
            break;

-olc.c, in bool show_commands(), add:
        case ED_WMAP: //worldmap.c
            show_olc_cmds (ch, wedit_table);
            break;

-olc.c, in const struct olc_cmd_type oedit_table, add:
    {"v5", oedit_value5},        //worldmap.c
    {"v6", oedit_value6},        //worldmap.c

-olc.c, at the bottom of the interpret tables after "const struct olc_cmd_type medit_table", add:
//worldmap.c
const struct olc_cmd_type wedit_table[] = {
/*  {   command        function    }, */
    {"show",        wedit_show},
    {"tile",        wedit_tile}, //create, delete, save
    {"sector",      wedit_sector},
    {"symbol",      wedit_symbol},
    {"name",        wedit_name},
    {"desc",        wedit_desc},
    {"visibility",  wedit_visibility},
    {"passable",    wedit_passable},
    {"exit",        wedit_exit}, //vnum, save, delete
    {"wlist",       wedit_wlist}, //tiles, exits
    {"save",        wedit_save}, //wmap, tile, exits
    {"reset",       wedit_reset}, //list (all), tile, add, delete
    {"clear",       wedit_clear}, //deletes tiles, exits, and resets
    {"reload",      wedit_reload},
    {"?",           show_help},
    {"version",     show_version},

    {NULL, 0,}
};

-olc.c, in bool edit_done(), add this just before RETURN FALSE;:
    ch->pcdata->wmap_sec = -1; //worldmap.c

-olc.c, in const struct editor_cmd_type editor_table, add:
    {"wedit", do_wedit}, //worldmap.c

-olc.c, in void do_redit(), add this under pRoom = ch->in_room;:
    if(is_wmap(ch,NULL)) //worldmap.c
    {
        send_to_char("Cannot use REdit on a world map room.\r\n",ch);
        return;
    }

-olc.c, in void do_resets(), add this at the top after RESET_DATA *pReset = NULL;:
    if(is_wmap(ch,NULL)) //worldmap.c
    {
        if(ch->desc->editor != ED_WMAP)
        {
            do_function(ch, &do_wedit, "");
            if(ch->desc->editor == ED_WMAP)
                wedit_reset(ch,argument);
            else
                send_to_char("Cannot modify resets on a world map room.\r\n",ch);
        }
        return;
    }

-olc.c, at the bottom of the file, add this:
//worldmap.c
void do_wedit (CHAR_DATA * ch, char *argument)
{
    WMAPTILE_DATA *tile;
    char arg1[MAX_STRING_LENGTH];

    argument = one_argument (argument, arg1);

    if (IS_NPC (ch))
        return;

    if (!is_wmap(ch, NULL))
    {
        send_to_char("You are not in a valid map location.\r\n", ch);
        return;
    }

    if (arg1[0] != '\0' && !str_cmp (arg1, "create"))
    {
        if (wedit_tile (ch, "create"))
            ch->desc->editor = ED_WMAP;
        return;
    }

    tile = find_wmap_tile(wmap_num(ch,NULL),wmap_x(ch,NULL),wmap_y(ch,NULL),wmap_z(ch,NULL));

    if(tile == NULL)
    {
        ch->desc->editor = ED_WMAP;
        //send_to_char ("WEdit:  There is no default wmap tile to edit.\r\n", ch);
    }
    else
    {
        ch->desc->pEdit = (void *) tile;
        ch->desc->editor = ED_WMAP;
    }
    return;
}

//worldmap.c
/* Wmap Interpreter, called by do_wedit. */
void wedit (CHAR_DATA * ch, char *argument)
{
    WMAPTILE_DATA *tile;
    char command[MAX_INPUT_LENGTH];
    char arg[MAX_STRING_LENGTH];
    int cmd;

    smash_tilde (argument);
    strcpy (arg, argument);
    argument = one_argument (argument, command);

    EDIT_WMAP (ch, tile);

    if (!str_cmp (command, "done"))
    {
        edit_done (ch);
        return;
    }

    if (command[0] == '\0')
    {
        wedit_show (ch, argument);
        return;
    }

    /* Search Table and Dispatch Command. */
    for (cmd = 0; wedit_table[cmd].name != NULL; cmd++)
    {
        if (!str_prefix (command, wedit_table[cmd].name))
        {
            if((*wedit_table[cmd].olc_fun) (ch, argument))
                return;
            return;
        }
    }
    /* Default to Standard Interpreter. */
    interpret (ch, arg);
    return;
}

-olc.h, find where the editors are defined such as ED_ROOM and add this to the list (adjust the number
  as needed):
#define ED_WMAP        7 //worldmap.c

-below that in the interpreter prototypes:
void    wedit           args( ( CHAR_DATA *ch, char *argument ) ); //worldmap.c

-olc.h, in the Interpreter Table Prototypes:
extern const struct olc_cmd_type    wedit_table[]; //worldmap.c

-below that in the editor commands:
DECLARE_DO_FUN( do_wedit    ); //worldmap.c

-olc.h, Object Editor Prototypes:
DECLARE_OLC_FUN( oedit_value5        ); //worldmap.c
DECLARE_OLC_FUN( oedit_value6        ); //worldmap.c

-olc.h, find "Return pointers to what is being edited", ie: "#define EDIT_MOB(Ch, Mob)", add:
#define EDIT_WMAP(Ch, Tile)    ( Tile = find_wmap_tile(wmap_num(ch,NULL),wmap_x(ch,NULL),wmap_y(ch,NULL),wmap_z(ch,NULL)) ) //worldmap.c

-olc_act.c, add the worldmap.h include at the top:
#include "worldmap.h" //worldmap.c

-olc_act.c, at the top under the #define AEDIT( fun ), add:
#define WEDIT( fun )        bool fun( CHAR_DATA *ch, char *argument ) //worldmap.c

extern WMAP_RESET_DATA     *wmap_reset_list[]; //worldmap.c
void save_wmap_resets(int wmap_index); //worldmap.c

-olc_act.c, in "const struct olc_help_type help_table", add:
    {"wedit", wmap_table, "WEdit commands."}, //worldmap.c

-olc_act.c, in bool show_help(), find the if check block for:
            else if (help_table[cnt].structure == skill_table)
            {
          <blah blah>
        }
  and add:
            //worldmap.c
            else if (help_table[cnt].structure == sector_flags)
            {
                show_seclist (ch);
                return FALSE;
            }
            else if (help_table[cnt].structure == wmap_table) //worldmap.c
            {
                send_to_char("WEdit commands\r\n"
                             " show\r\n"
                             " tile <create|delete|save>\r\n"
                             " sector <type> | sector fill <type> | sector walk <type>\r\n"
                             " sector circle/square/fractal <type> <distance> <true|false>\r\n"
                             " symbol <X>\r\n"
                             " name <text>\r\n"
                             " desc (enters into append mode)\r\n"
                             " visibility <#>\r\n"
                             " passable <yes/true | no/false>\r\n"
                             " exit <vnum|save|delete>\r\n"
                             " wlist tiles [all] | wlist exits\r\n"
                             " reset [all|wmap#] | reset [modify|mob|obj|delete]>\r\n"
                             " reload\r\n"
                             " save <wmap|tile|exits>\r\n",ch);
                return FALSE;
            }

-olc_act.c, in "REDIT (redit_show)", change the vnum/sector part to this to account for the new sector
  flag table code:
    //worldmap.c
    sprintf (buf, "Vnum:       [%5d]\r\nSector:     [%s]\r\n",
             pRoom->vnum, sector_flags[pRoom->sector_type].name);
    strcat (buf1, buf);

-olc_act.c, in bool set_obj_values(), under "case ITEM_PORTAL:", add:
                case 4: //worldmap.c
                    send_to_char ("WMAP VNUM SET.\r\n\r\n", ch);
                    pObj->value[4] = atoi (argument);
                    break;
                case 5: //worldmap.c
                    send_to_char ("X COORD SET.\r\n\r\n", ch);
                    pObj->value[5] = atoi (argument);
                    break;
                case 6: //worldmap.c
                    send_to_char ("Y COORD SET.\r\n\r\n", ch);
                    pObj->value[6] = atoi (argument);
                    break;

-olc_act.c, find "OEDIT (oedit_value4)" and add under it:
OEDIT (oedit_value5) //worldmap.c
{
    if (oedit_values (ch, argument, 5))
        return TRUE;

    return FALSE;
}

OEDIT (oedit_value6) //worldmap.c
{
    if (oedit_values (ch, argument, 6))
        return TRUE;

    return FALSE;
}

-olc_act.c, at the bottom, this entire chunk of code/functions can be pasted:
//worldmap.c
void show_seclist (CHAR_DATA * ch)
{
    int sec;
    BUFFER *buffer;
    char buf[MAX_STRING_LENGTH];

    buffer = new_buf ();

    for (sec = 0; sec < SECT_MAX; sec++)
    {
        if ((sec % 21) == 0)
            add_buf (buffer,
                     "Name           mv    r    g    b  walls floor w.map\r\n");

        sprintf (buf, "%-14s %2d  %3d  %3d  %3d    %s{x     %s{x     %s{x\r\n",
                sector_flags[sec].name, sector_flags[sec].move,
                sector_flags[sec].red, sector_flags[sec].blue, sector_flags[sec].green,
                sector_flags[sec].wall, sector_flags[sec].floor, sector_flags[sec].wmap_symb);

        add_buf (buffer, buf);
    }

    page_to_char (buf_string (buffer), ch);
    free_buf (buffer);

    return;
}

WEDIT (wedit_show)
{
    WMAPTILE_DATA *tile;

    EDIT_WMAP (ch, tile);

    if(tile == NULL)
    {
        send_to_char("No tile present.\r\n",ch);
        return FALSE;
    }

    printf_to_char(ch,"Coords:     %d %d %d\r\n"
                      "Visibility: %d\r\n"
                      "Passable:   %s\r\n"
                      "Symbol:     %s{x\r\n"
                      "Name:       %s\r\n"
                      "Desc:\r\n%s\r\n",
    tile->x, tile->y, tile->z, tile->vis, tile->pass == 0 ? "TRUE" : "FALSE",
    tile->symb, tile->name, tile->desc);
    return FALSE;
}

WEDIT (wedit_tile) //create, delete, save
{
    WMAPTILE_DATA *tile;

    if (argument[0] == '\0')
    {
        send_to_char ("Syntax:  create|delete|save\r\n", ch);
        return FALSE;
    }

    if (!str_cmp(argument, "save"))
    {
        save_wmap_tiles(wmap_num(ch,NULL));
        send_to_char("Map tiles saved.\r\n", ch);
        return TRUE;
    }

    if (!str_cmp(argument, "create"))
    {
        int x = wmap_x(ch, NULL);
        int y = wmap_y(ch, NULL);
        int z = wmap_z(ch, NULL);
        int wmap_index = wmap_num(ch, NULL);

        //tile = find_wmap_tile(wmap_index,x,y,z);
        if(find_wmap_tile(wmap_index,x,y,z) != NULL)
        {
            send_to_char("Map tile already present.\r\n", ch);
            return FALSE;
        }

        CREATE( tile, WMAPTILE_DATA, 1 );
        LINK( tile, first_wmaptile, last_wmaptile, next, prev );
        tile->wmap_index = wmap_index;
        tile->x = x;
        tile->y = y;
        tile->z = z;
        tile->vis = 0;
        tile->pass = 0;
        send_to_char("Map tile created.\r\n", ch);
        return TRUE;
    }

    EDIT_WMAP (ch, tile);

    if(tile == NULL)
    {
        send_to_char("No tile present.\r\n",ch);
        return FALSE;
    }

    if (!str_cmp(argument, "delete"))
    {
        free_string( tile->name );
        free_string( tile->desc );
        free_string(tile->symb);
        UNLINK( tile, first_wmaptile, last_wmaptile, next, prev );
        free(tile);
        send_to_char("World Map Tile deleted.\r\n", ch);
        return TRUE;
    }
    return FALSE;
}

void flood_fill args((CHAR_DATA *ch, int wmap_index, int x, int y, int replacement));
void fractal_fill args((CHAR_DATA *ch, int wmap_index, int x, int y, int distance, int sector, bool use_decay));
void square_fill args((CHAR_DATA *ch, int wmap_index, int x, int y, int distance, int sector, bool font));
void circle_fill args((CHAR_DATA *ch, int wmap_index, int x, int y, int distance, int sector, bool font));

WEDIT (wedit_sector)
{
    char arg1[MAX_INPUT_LENGTH];
    argument = one_argument(argument, arg1);
    int value;

    if (arg1[0] == '\0')
    {
        send_to_char ("Syntax:  sector [type]\r\n", ch);
        send_to_char ("Syntax:  sector fill [type]  --flood fill with sector\r\n", ch);
        send_to_char ("Syntax:  sector square [type] [distance] [true|false]  --draw square filled with sector, adjust for font height?\r\n", ch);
        send_to_char ("Syntax:  sector circle [type] [distance] [true|false]  --draw circle filled with sector, adjust for font height?\r\n", ch);
        send_to_char ("Syntax:  sector fractal [type] [distance] [true|false]  --draw fractal filled with sector, more filled center?\r\n", ch);
        send_to_char ("Syntax:  sector walk [type]  --use without 'type' to toggle off\r\n", ch);
        return FALSE;
    }

    if(!str_cmp(arg1,"walk"))
    {
        if(argument[0] == '\0')
        {
            ch->pcdata->wmap_sec = -1;
            send_to_char("Sector walk OFF.\r\n",ch);
            return FALSE;
        }
        if ((value = sector_lookup(argument)) < 0 || value >= SECT_MAX)
        {
            send_to_char("That isn't a valid sector!\r\n",ch);
            return FALSE;
        }
        wmap_table[wmap_num(ch,NULL)].grid[wmap_x(ch, NULL)][wmap_y(ch, NULL)] = value;
        send_to_char("Map tile terrain set.\r\n", ch);
        ch->pcdata->wmap_sec = value;
        send_to_char("Sector walk ON.\r\n",ch);
        return TRUE;
    }

    if(!str_cmp(arg1,"fill"))
    {
        if(argument[0] == '\0')
        {
            send_to_char("Syntax:  fill [type]\r\n",ch);
            return FALSE;
        }
        if ((value = sector_lookup(argument)) < 0 || value >= SECT_MAX)
        {
            send_to_char("That isn't a valid sector!\r\n",ch);
            return FALSE;
        }
        flood_fill(ch, wmap_num(ch,NULL), wmap_x(ch,NULL), wmap_y(ch,NULL), value);
        send_to_char("Map tile terrain set.\r\n", ch);
        return TRUE;
    }

    if(!str_cmp(arg1,"square"))
    {
        char arg2[MAX_INPUT_LENGTH];
        char arg3[MAX_INPUT_LENGTH];
        argument = one_argument(argument, arg2);
        argument = one_argument(argument, arg3);
        int dist;
        bool font = FALSE;

        if(arg2[0] == '\0' || arg3[0] == '\0' || argument[0] == '\0' || !is_number(arg3)
        || (str_cmp(argument,"true") && str_cmp(argument,"false") ))
        {
            send_to_char("Syntax:  sector quare [type] [distance] [true|false]\r\n",ch);
            return FALSE;
        }
        if ((value = sector_lookup(arg2)) < 0 || value >= SECT_MAX)
        {
            send_to_char("That isn't a valid sector!\r\n",ch);
            return FALSE;
        }
        dist = atoi(arg3);
        if(!str_cmp(argument,"true"))
            font = TRUE;
        square_fill(ch, wmap_num(ch,NULL), wmap_x(ch,NULL), wmap_y(ch,NULL), dist, value, font);
        send_to_char("Map tile terrain set.\r\n", ch);
        return TRUE;
    }

    if(!str_cmp(arg1,"circle"))
    {
        char arg2[MAX_INPUT_LENGTH];
        char arg3[MAX_INPUT_LENGTH];
        argument = one_argument(argument, arg2);
        argument = one_argument(argument, arg3);
        int dist;
        bool font = FALSE;

        if(arg2[0] == '\0' || arg3[0] == '\0' || argument[0] == '\0' || !is_number(arg3)
        || (str_cmp(argument,"true") && str_cmp(argument,"false") ))
        {
            send_to_char("Syntax:  sector circle [type] [distance] [true|false]\r\n",ch);
            return FALSE;
        }
        if ((value = sector_lookup(arg2)) < 0 || value >= SECT_MAX)
        {
            send_to_char("That isn't a valid sector!\r\n",ch);
            return FALSE;
        }
        dist = atoi(arg3);
        if(!str_cmp(argument,"true"))
            font = TRUE;
        circle_fill(ch, wmap_num(ch,NULL), wmap_x(ch,NULL), wmap_y(ch,NULL), dist, value, font);
        send_to_char("Map tile terrain set.\r\n", ch);
        return TRUE;
    }

    if(!str_cmp(arg1,"fractal"))
    {
        char arg2[MAX_INPUT_LENGTH];
        char arg3[MAX_INPUT_LENGTH];
        argument = one_argument(argument, arg2);
        argument = one_argument(argument, arg3);
        int dist;
        bool decay = FALSE;

        if(arg2[0] == '\0' || arg3[0] == '\0' || argument[0] == '\0' || !is_number(arg3)
        || (str_cmp(argument,"true") && str_cmp(argument,"false") ))
        {
            send_to_char("Syntax:  sector fractal [type] [distance] [true|false]\r\n",ch);
            return FALSE;
        }
        if ((value = sector_lookup(arg2)) < 0 || value >= SECT_MAX)
        {
            send_to_char("That isn't a valid sector!\r\n",ch);
            return FALSE;
        }
        dist = atoi(arg3);
        if(!str_cmp(argument,"true"))
            decay = TRUE;
        fractal_fill(ch, wmap_num(ch,NULL), wmap_x(ch,NULL), wmap_y(ch,NULL), dist, value, decay);
        send_to_char("Map tile terrain set.\r\n", ch);
        return TRUE;
    }

    if ((value = sector_lookup(arg1)) < 0 || value >= SECT_MAX)
    {
        send_to_char("That isn't a valid sector!\r\n",ch);
        return FALSE;
    }

    wmap_table[wmap_num(ch,NULL)].grid[wmap_x(ch, NULL)][wmap_y(ch, NULL)] = value;
    send_to_char("Map tile terrain set.\r\n", ch);
    return TRUE;
}

WEDIT (wedit_symbol)
{
    WMAPTILE_DATA *tile;

    EDIT_WMAP (ch, tile);

    if(tile == NULL)
    {
        wedit_tile(ch,"create");
        EDIT_WMAP (ch, tile);
    }

    if (argument[0] == '\0')
    {
        send_to_char ("Syntax:  symbol <X> \r\n", ch);
        return FALSE;
    }

    free_string(tile->symb);
    if(!str_cmp(argument,"none"))
        tile->symb = str_dup(""); 
    else
        tile->symb = str_dup(argument);

    send_to_char ("Map tile custom symbol set.\r\n", ch);
    return TRUE;
}

WEDIT (wedit_name)
{
    WMAPTILE_DATA *tile;

    EDIT_WMAP (ch, tile);

    if(tile == NULL)
    {
        wedit_tile(ch,"create");
        EDIT_WMAP (ch, tile);
    }

    if (argument[0] == '\0')
    {
        send_to_char ("Syntax:  name <text>\r\n", ch);
        return FALSE;
    }

    free_string(tile->name);
    if(!str_cmp(argument,"none"))
        tile->name = str_dup(""); 
    else
        tile->name = str_dup(argument);
    send_to_char ("Map tile name set.\r\n", ch);
    return TRUE;
}

WEDIT (wedit_desc)
{
    WMAPTILE_DATA *tile;

    EDIT_WMAP (ch, tile);

    if(tile == NULL)
    {
        wedit_tile(ch,"create");
        EDIT_WMAP (ch, tile);
    }

    if (argument[0] == '\0')
    {
        string_append (ch, &tile->desc);
        return TRUE;
    }

    send_to_char ("Syntax:  desc\r\n", ch);
    return FALSE;
}

WEDIT (wedit_visibility)
{
    WMAPTILE_DATA *tile;

    EDIT_WMAP (ch, tile);

    if(tile == NULL)
    {
        send_to_char("No tile present.\r\n",ch);
        return FALSE;
    }

    if (argument[0] == '\0' || !is_number(argument) || atoi(argument) > MAX_WMAP_SCAN)
    {
        printf_to_char (ch,"Syntax:  visibility <1-%d>\r\n", MAX_WMAP_SCAN);
        return FALSE;
    }

    tile->vis = atoi(argument);
    send_to_char ("Map tile visibility set.\r\n", ch);
    return TRUE;
}

WEDIT (wedit_passable)
{
    WMAPTILE_DATA *tile;

    EDIT_WMAP (ch, tile);

    if(tile == NULL)
    {
        send_to_char("No tile present.\r\n",ch);
        return FALSE;
    }

    if (argument[0] == '\0')
    {
        send_to_char ("Syntax:  passable <yes/true | no/false>\r\n", ch);
        return FALSE;
    }

    if (!str_cmp(argument,"yes") ||  !str_cmp(argument,"true"))
        tile->pass = 0;
    else if (!str_cmp(argument,"no") ||  !str_cmp(argument,"false"))
        tile->pass = 1;
    else
    {
        send_to_char ("Syntax:  passable <yes/true | no/false>\r\n", ch);
        return FALSE;
    }
    send_to_char ("Map tile passability set.\r\n", ch);
    return TRUE;
}

WEDIT (wedit_exit) //vnum, save, delete
{
    char arg1[MAX_INPUT_LENGTH];
    int x = wmap_x(ch, NULL);
    int y = wmap_y(ch, NULL);
    int z = wmap_z(ch, NULL);
    int wmap_index = wmap_num(ch, NULL);
    WMAP_EXIT *exit;

    argument = one_argument(argument, arg1);

    if (arg1[0] == '\0')
    {
        send_to_char ("Syntax:  <vnum>\r\n"
                      "Syntax:  list [all]\r\n"
                      "Syntax:  save|delete\r\n", ch);
        return FALSE;
    }

    if (is_number(arg1))
    {
        int room_vnum = atoi(arg1);

        if (room_vnum < 1 || !get_room_index(room_vnum))
        {
            send_to_char("Invalid room vnum.\r\n", ch);
            return FALSE;
        }

        if((exit = find_wmap_exit(wmap_index,x,y,z)) != NULL)
        {
            send_to_char("Map exit already present.\r\n",ch);
            return FALSE;
        }

        add_wmap_exit(wmap_index, wmap_x(ch,NULL), wmap_y(ch,NULL), wmap_z(ch,NULL), room_vnum);
        send_to_char("Map exit created.\r\n", ch);
        return TRUE;
    }

    if (!str_cmp(arg1, "save"))
        save_wmap_exits();

    if (!str_cmp(arg1, "list"))
    {
        bool exits_found = false;

        for( exit = first_wmapexit; exit != NULL; exit = exit->next )
        {
            if(str_cmp(argument,"all") && exit->wmap_index != wmap_index) continue;
            if (!exits_found)
            {
                send_to_char("Map Exits:\r\n", ch);
                send_to_char("--------------------------\r\n", ch);
                exits_found = true;
            }

            printf_to_char(ch, "Wmap %s(%d) (X: %d, Y: %d, Z: %d) -> Room %d\r\n", 
                    wmap_table[exit->wmap_index].name, exit->wmap_index, exit->x, exit->y, exit->z, exit->room_vnum);
        }

        if (!exits_found)
            send_to_char("No map exits are currently set.\r\n", ch);
    }

    if (!str_cmp(arg1, "delete"))
    {
        exit = find_wmap_exit(wmap_index,x,y,z);
        if (exit != NULL)
        {
            UNLINK( exit, first_wmapexit, last_wmapexit, next, prev );
            free(exit);
            send_to_char("Map exit removed.\r\n", ch);
            return TRUE;
        }
        else
            send_to_char("No map exit found at that location.\r\n", ch);
    }
    return FALSE;
}

WEDIT (wedit_wlist) //tiles, exits
{
    WMAPTILE_DATA *tile;
    char arg1[MAX_INPUT_LENGTH];
    argument = one_argument(argument, arg1);

    if (arg1[0] == '\0')
        send_to_char ("Syntax:  list <tiles|exits>\r\n", ch);
    else if (!str_cmp(arg1,"tiles"))
    {
        for( tile = first_wmaptile; tile != NULL; tile = tile->next )
        {
            if(str_cmp(argument,"all") && tile->wmap_index != wmap_num(ch,NULL)) continue;
            printf_to_char(ch, "Coords %s(%d) %d %d %d %d %d\n", wmap_table[tile->wmap_index].name, tile->wmap_index, tile->x, tile->y, tile->z, tile->vis, tile->pass);
        }
    }
    else if (!str_cmp(arg1,"exits"))
    {
        WMAP_EXIT *exit;
        bool exits_found = false;

        for( exit = first_wmapexit; exit != NULL; exit = exit->next )
        {
            if(str_cmp(argument,"all") && exit->wmap_index != wmap_num(ch,NULL)) continue;
            if (!exits_found)
            {
                send_to_char("Map Exits:\r\n", ch);
                send_to_char("--------------------------\r\n", ch);
                exits_found = true;
            }

            printf_to_char(ch, "%s(%d) (X: %d, Y: %d, Z: %d) -> Room %d\r\n", 
                    wmap_table[exit->wmap_index].name, exit->wmap_index, exit->x, exit->y, exit->z, exit->room_vnum);
        }

        if (!exits_found)
            send_to_char("No map exits are currently set.\r\n", ch);
    }
    else
        send_to_char ("Syntax:  list <tiles|exits>\r\n", ch);

    return FALSE;
}

WEDIT (wedit_save) //wmap, tile, exits
{
    int wmap_index = -1;

    if (argument[0] == '\0')
    {
        send_to_char (    "Syntax:  save wmap   -- saves PNG map file\r\n"
                        "Syntax:  save tiles  -- saves maptile file\r\n"
                        "Syntax:  save exits  -- saves exits file\r\n", ch);
    }
    else if (!str_cmp(argument,"wmap"))
    {
        WMAP_TYPE* current_wmap = get_wmap_ch(ch, &wmap_index);
        if (save_image(current_wmap->filename, wmap_index)) 
            printf_to_char(ch,"The map '%s' has been saved!\r\n", current_wmap->name);
        else
            send_to_char("Failed to save the map.\r\n",ch);
    }
    else if (!str_cmp(argument,"tiles"))
    {
        WMAP_TYPE* current_wmap = get_wmap_ch(ch, &wmap_index);
        save_wmap_tiles(wmap_index);
        printf_to_char(ch,"Maptiles for '%s' has been saved!\r\n", current_wmap->name);
    }
    else if (!str_cmp(argument,"exits"))
    {
        save_wmap_exits();
        send_to_char("Map exits have been saved.\r\n",ch);
    }
    else
    {
        send_to_char ("Syntax:  save wmap   -- saves PNG map file\r\n"
                      "Syntax:  save tiles  -- saves maptile file\r\n"
                      "Syntax:  save exits  -- saves exits file\r\n", ch);
    }
     return FALSE;
}

WEDIT (wedit_reset)
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char arg3[MAX_INPUT_LENGTH];
    char arg4[MAX_INPUT_LENGTH];
    char arg5[MAX_INPUT_LENGTH];
    char arg6[MAX_INPUT_LENGTH];

    argument = one_argument(argument, arg1); // mob / obj / delete / wmap / all/wmap#
    argument = one_argument(argument, arg2); // vnum
    argument = one_argument(argument, arg3); // mob: max, obj: on
    argument = one_argument(argument, arg4); // mob: x, obj: mob_vnum
    argument = one_argument(argument, arg5); // mob: y, obj: wear|hold
    argument = one_argument(argument, arg6); // mob: z, obj: max

    int wmap_index = wmap_num(ch, NULL);
    int x = wmap_x(ch, NULL);
    int y = wmap_y(ch, NULL);
    int z = wmap_z(ch, NULL);

    if (wmap_index == -1)
    {
        send_to_char("You must be on a valid map to set a reset.\r\n", ch);
        return FALSE;
    }

    if(arg1[0] == '\0' || !str_cmp(arg1,"all") || is_number(arg1))
    {
        bool found = FALSE, all = FALSE;

        if (arg1[0] != '\0' && !is_number(arg1))
        {
            if(!str_cmp(arg1,"all"))
                all = TRUE;
            else
            {
                send_to_char("Syntax:  reset (all|wmap#)\r\n", ch);
                return FALSE;
            }
        }
        else if(arg1[0] != '\0')
        {
            wmap_index = atoi(arg1);
            if (wmap_index < 0 || wmap_index >= MAX_WMAP)
            {
                send_to_char("Invalid wmap index. Use 'wmaptable' for information.\r\n", ch);
                return FALSE;
            }
            all = TRUE;
        }


        send_to_char("Num  WMap        Type Name            Vnum  Max   X    Y    Z    Extra\r\n", ch);
        send_to_char("----------------------------------------------------------------------\r\n", ch);

        WMAP_RESET_DATA *reset;
        int reset_count = 0;
        for (reset = wmap_reset_list[wmap_index]; reset != NULL; reset = reset->next)
        {
            if(!all && (reset->x != x || reset->y != y || reset->z != z)) continue;

            const char *name = "Unknown";
            char extra[50];
            if (reset->reset_type == RESET_TYPE_MOB)
            {
                MOB_INDEX_DATA *mob = get_mob_index(reset->vnum);
                if (mob)
                    name = mob->short_descr;
                sprintf(extra, "Mob");
            }
            else if (reset->reset_type == RESET_TYPE_OBJ)
            {
                OBJ_INDEX_DATA *obj = get_obj_index(reset->vnum);
                if (obj)
                    name = obj->short_descr;
                sprintf(extra, "Obj");
            }
            else if (reset->reset_type == RESET_TYPE_OBJ_ON_MOB)
            {
                OBJ_INDEX_DATA *obj = get_obj_index(reset->vnum);
                if (obj)
                    name = obj->short_descr;
                sprintf(extra, "Obj on Mob %d (%s)", reset->mob_vnum, reset->wear ? "wear" : "hold");
            }

            if(!all)
                printf_to_char(ch, "%-4d %-10s: %-20.20s %-5d [%-2d] [%-4d %-4d %-4d] %s\r\n",
                    reset_count++, wmap_table[wmap_index].name, name, reset->vnum, reset->max, reset->x, reset->y, reset->z, extra);
            else
                printf_to_char(ch, "     %-10s: %-20.20s %-5d [%-2d] [%-4d %-4d %-4d] %s\r\n",
                    wmap_table[wmap_index].name, name, reset->vnum, reset->max, reset->x, reset->y, reset->z, extra);
            found = true;
        }

        if (!found)
            send_to_char("No map resets found.\r\n", ch);
        return FALSE;
    }
    else if((!str_cmp(arg1,"mob") || !str_cmp(arg1,"obj")) && arg2[0] != '\0')
    {
        int reset_type;
        if (!str_prefix(arg1, "mob"))
            reset_type = RESET_TYPE_MOB;
        else if (!str_prefix(arg1, "obj"))
            reset_type = RESET_TYPE_OBJ;
        else
        {
            send_to_char("Type must be 'mob' or 'obj'.\r\n", ch);
            return FALSE;
        }

        if (!is_number(arg2))
        {
            send_to_char("Vnum must be numerical.\r\n", ch);
            return FALSE;
        }

        int vnum = atoi(arg2);
        int max = 1;

        //regular mob|obj in room reset
        if (arg3[0] != '\0' && str_cmp(arg3, "on") && is_number(arg3))
        {
            if ((max = atoi(arg3)) < 1)
            {
                send_to_char("Maximum must be at least 1.\r\n", ch);
                return FALSE;
            }


            if (arg4[0] != '\0' || arg5[0] != '\0' || arg6[0] != '\0'
            || !is_number(arg4) || !is_number(arg5) || !is_number(arg6))
            {
                send_to_char("Syntax:  reset <mob|obj> <vnum> [max] [x][y][z]\r\n", ch);
                return FALSE;
            }
            x = atoi(arg4);
            y = atoi(arg5);
            z = atoi(arg6);

            if (x < 0 || x >= wmap_table[wmap_index].max_x || 
                y < 0 || y >= wmap_table[wmap_index].max_y)
            {
                send_to_char("Coordinates are out of map bounds.\r\n", ch);
                return FALSE;
            }
        }

        if (reset_type == RESET_TYPE_MOB)
        {
            if (!get_mob_index(vnum))
            {
                printf_to_char(ch, "Mob vnum %d does not exist.\r\n", vnum);
                return FALSE;
            }
        }
        else if (reset_type == RESET_TYPE_OBJ && str_cmp(arg3, "on"))
        {
            if (!get_obj_index(vnum))
            {
                printf_to_char(ch, "Object vnum %d does not exist.\r\n", vnum);
                return FALSE;
            }
        }

        //reset obj onto a mob
        if (reset_type == RESET_TYPE_OBJ && !str_cmp(arg3, "on"))
        {
            if (arg4[0] == '\0' || arg5[0] == '\0')
            {
                send_to_char("Syntax:  reset obj <vnum> on <mob_vnum> <wear|hold> [max]\r\n", ch);
                return FALSE;
            }

            if (!is_number(arg4))
            {
                send_to_char("Mob vnum must be a number.\r\n", ch);
                return FALSE;
            }

            int mob_vnum = atoi(arg4);
            if (!get_mob_index(mob_vnum))
            {
                printf_to_char(ch, "Mob vnum %d does not exist.\r\n", mob_vnum);
                return FALSE;
            }

            OBJ_INDEX_DATA *pObjIndex = get_obj_index(vnum);
            if (!pObjIndex)
            {
                printf_to_char(ch, "Object vnum %d does not exist.\r\n", vnum);
                return FALSE;
            }

            bool wear = !str_cmp(arg5, "wear");
            bool hold = !str_cmp(arg5, "hold");
            if (!wear && !hold)
            {
                send_to_char("Argument must be 'wear' or 'hold'.\r\n", ch);
                return FALSE;
            }

            if (arg6[0] != '\0' && is_number(arg6))
            {
                if ((max = atoi(arg6)) < 1)
                {
                    send_to_char("Maximum must be at least 1.\r\n", ch);
                    return FALSE;
                }
            }

            WMAP_RESET_DATA *mob_reset = NULL;
            for (WMAP_RESET_DATA *r = wmap_reset_list[wmap_index]; r != NULL; r = r->next)
            {
                if (r->reset_type == RESET_TYPE_MOB && r->vnum == mob_vnum)
                {
                    mob_reset = r;
                    break;
                }
            }

            if (!mob_reset)
            {
                printf_to_char(ch, "No reset found for mob vnum %d on this map.\r\n", mob_vnum);
                return FALSE;
            }

            x = mob_reset->x;
            y = mob_reset->y;
            z = mob_reset->z;

            reset_type = RESET_TYPE_OBJ_ON_MOB;
        }

        WMAP_RESET_DATA *reset = malloc(sizeof(WMAP_RESET_DATA));
        if (!reset)
        {
            send_to_char("Memory allocation failed!\r\n", ch);
            return FALSE;
        }

        reset->reset_type = reset_type;
        reset->vnum = vnum;
        reset->wmap_index = wmap_index;
        reset->x = x;
        reset->y = y;
        reset->z = z;
        reset->max = max;
        reset->mob_vnum = (reset_type == RESET_TYPE_OBJ_ON_MOB) ? atoi(arg4) : -1;
        reset->wear = (reset_type == RESET_TYPE_OBJ_ON_MOB && !str_cmp(arg5, "wear"));
        reset->next = wmap_reset_list[wmap_index];
        wmap_reset_list[wmap_index] = reset;

        save_wmap_resets(wmap_index);

        if (reset_type == RESET_TYPE_OBJ_ON_MOB)
        {
            printf_to_char(ch, "Reset added: Object %d [max %d] on mob %d (%s) at [X %d Y %d Z %d] on wmap %s\r\n",
                    vnum, max, reset->mob_vnum, reset->wear ? "wear" : "hold", x, y, z, wmap_table[wmap_index].name);
        }
        else
        {
            printf_to_char(ch, "Reset added: %s %d [max %d] at [X %d Y %d Z %d] on wmap %s\r\n",
                    reset_type == RESET_TYPE_MOB ? "Mob" : "Object", vnum, max, x, y, z, wmap_table[wmap_index].name);
        }
    }
    else if(!str_cmp(arg1,"delete") && arg2[0] != '\0' && (is_number(arg2) || !str_cmp(arg2,"all")))
    {
        WMAP_RESET_DATA *reset;
        WMAP_RESET_DATA *reset_next;
        WMAP_RESET_DATA *reset_nest;
        WMAP_RESET_DATA *prev = NULL;
        int reset_num = atoi(arg2);
        int current_num = 0;

        if(is_number(arg2))
        {
            int obj_reset = 0;
            for (reset = wmap_reset_list[wmap_index]; reset != NULL; reset = reset_next)
            {
                reset_next = reset->next;

                if(reset->x != x || reset->y != y || reset->z != z) continue;
                if (current_num == reset_num)
                {
                    if (prev)
                        prev->next = reset->next;
                    else
                        wmap_reset_list[wmap_index] = reset->next;

                    if (reset->reset_type == RESET_TYPE_OBJ_ON_MOB)
                        printf_to_char(ch, "Reset #%d removed: Object %d on mob %d at (%d, %d, %d).\r\n",
                                reset_num, reset->vnum, reset->mob_vnum, reset->x, reset->y, reset->z);
                    else
                    {
                        if (reset->reset_type == RESET_TYPE_MOB)
                        {
                            for (reset_nest = wmap_reset_list[wmap_index]; reset_nest != NULL; reset_nest = reset_nest->next)
                            {
                                if(reset_nest->x != x || reset_nest->y != y || reset_nest->z != z) continue;
                                if(reset_nest->reset_type == RESET_TYPE_OBJ_ON_MOB && reset_nest->mob_vnum == reset->vnum)
                                {
                                    obj_reset = reset->vnum;
                                    break;
                                }
                            }
                        }

                        printf_to_char(ch, "Reset #%d removed: %s %d at (%d, %d, %d).\r\n",
                                reset_num, reset->reset_type == RESET_TYPE_MOB ? "Mob" : "Object",
                                reset->vnum, reset->x, reset->y, reset->z);

                        free(reset);
                        if(obj_reset == 0)
                        {
                            save_wmap_resets(wmap_index);
                            return TRUE;
                        }
                        else
                            break;
                    }
                }
                if(obj_reset == 0)
                {
                    prev = reset;
                    current_num++;
                }
            }
            if(obj_reset > 0)
            {
                prev = NULL;
                for (reset = wmap_reset_list[wmap_index]; reset != NULL; reset = reset_next)
                {
                    reset_next = reset->next;

                    if(reset->x == x && reset->y == y && reset->z == z
                    && reset->reset_type == RESET_TYPE_OBJ_ON_MOB
                    && reset->mob_vnum == obj_reset)
                    {
                        if (prev)
                            prev->next = reset->next;
                        else
                            wmap_reset_list[wmap_index] = reset->next;
                        free(reset);
                        continue;
                    }
                    prev = reset;
                }
                save_wmap_resets(wmap_index);
                return TRUE;
            }
            printf_to_char(ch, "No reset found with number %d.\r\n", reset_num);
            return FALSE;
        }
        if(!str_cmp(arg2,"all"))
        {
            for (reset = wmap_reset_list[wmap_index]; reset != NULL; reset = reset->next)
            {
                if(reset->x != x || reset->y != y || reset->z != z) continue;
                free(reset);
            }
            return TRUE;
        }
    }
    //reset modify <#> <vnum>
    else if(!str_cmp(arg1,"modify"))
    {
        if(arg2[0] == '\0' || arg3[0] == '\0' || !is_number(arg2) || !is_number(arg3))
        {
            send_to_char("Syntax:  modify <#> <nvum>\r\n",ch);
            return FALSE;
        }

        WMAP_RESET_DATA *reset;
        WMAP_RESET_DATA *reset_next;
        WMAP_RESET_DATA *reset_nest;
        int reset_num = atoi(arg2);
        int new_vnum = atoi(arg3);
        int current_num = 0;
        int obj_reset = 0;

        for (reset = wmap_reset_list[wmap_index]; reset != NULL; reset = reset_next)
        {
            reset_next = reset->next;

            if(reset->x != x || reset->y != y || reset->z != z) continue;
            if (current_num == reset_num)
            {
                if (reset->reset_type == RESET_TYPE_MOB)
                {
                    if (!get_mob_index(new_vnum))
                    {
                        printf_to_char(ch, "Mob vnum %d does not exist.\r\n", new_vnum);
                        return FALSE;
                    }
                }
                else
                {
                    if (!get_obj_index(new_vnum))
                    {
                        printf_to_char(ch, "Object vnum %d does not exist.\r\n", new_vnum);
                        return FALSE;
                    }
                }

                if (reset->reset_type == RESET_TYPE_OBJ_ON_MOB)
                {
                    reset->vnum = new_vnum;
                    printf_to_char(ch, "Reset #%d modified: Object %d on mob %d at (%d, %d, %d).\r\n",
                            reset_num, reset->vnum, reset->mob_vnum, reset->x, reset->y, reset->z);
                }
                else
                {
                    if (reset->reset_type == RESET_TYPE_MOB)
                    {
                        for (reset_nest = wmap_reset_list[wmap_index]; reset_nest != NULL; reset_nest = reset_nest->next)
                        {
                            if(reset_nest->x != x || reset_nest->y != y || reset_nest->z != z) continue;
                            if(reset_nest->reset_type == RESET_TYPE_OBJ_ON_MOB && reset_nest->mob_vnum == reset->vnum)
                            {
                                obj_reset = reset->vnum;
                                reset->vnum = new_vnum;
                                break;
                            }
                        }
                    }

                    reset->vnum = new_vnum;

                    printf_to_char(ch, "Reset #%d modified: %s %d at (%d, %d, %d).\r\n",
                            reset_num, reset->reset_type == RESET_TYPE_MOB ? "Mob" : "Object",
                            reset->vnum, reset->x, reset->y, reset->z);

                    if(obj_reset == 0)
                    {
                        save_wmap_resets(wmap_index);
                        return TRUE;
                    }
                    else
                        break;
                }
            }
            if(obj_reset == 0)
                current_num++;
        }
        if(obj_reset > 0)
        {
            for (reset = wmap_reset_list[wmap_index]; reset != NULL; reset = reset_next)
            {
                reset_next = reset->next;

                if(reset->x == x && reset->y == y && reset->z == z
                && reset->reset_type == RESET_TYPE_OBJ_ON_MOB
                && reset->mob_vnum == obj_reset)
                {
                    reset->mob_vnum = new_vnum;
                    continue;
                }
            }
            save_wmap_resets(wmap_index);
            return TRUE;
        }
        printf_to_char(ch, "No reset found with number %d.\r\n", reset_num);
        return FALSE;
    }
    else if(!str_cmp(arg1,"wmap"))
    {
        process_wmap_resets();
        send_to_char("World Map reset.\r\n",ch);
        return FALSE;
    }
    else
    {
        send_to_char("Syntax:  reset (all|wmap#)\r\n"
                     "Syntax:  reset wmap  --loads wmap resets\r\n"
                     "Syntax:  reset modify <#> <vnum>  --changes vnum of reset\r\n"
                     "Syntax:  reset <mob|obj> <vnum> [max] [x][y][z]\r\n"
                     "Syntax:  reset obj <vnum> on <mob_vnum> <wear|hold> [max]\r\n"
                     "Syntax:  reset delete <#>\r\n", ch);
        return FALSE;
    }
    return TRUE;
}

//clears a tile of exit data, tiles, and resets
WEDIT (wedit_clear)
{
    int wmap_index = wmap_num(ch, NULL);
    int x = wmap_x(ch, NULL);
    int y = wmap_y(ch, NULL);
    int z = wmap_z(ch, NULL);
    bool save_reset = FALSE, save_exit = FALSE, save_tile = FALSE;

    if (wmap_index == -1)
    {
        send_to_char("You must be on a valid map to set a reset.\r\n", ch);
        return FALSE;
    }

    //resets
    WMAP_RESET_DATA *reset;
    for (reset = wmap_reset_list[wmap_index]; reset != NULL; reset = reset->next)
    {
        if(reset->x != x || reset->y != y || reset->z != z) continue;
        free(reset);
        save_reset = TRUE;
    }

    //exits
    WMAP_EXIT *exit;
    for( exit = first_wmapexit; exit != NULL; exit = exit->next )
    {
        if(exit->x != x || exit->y != y || exit->z != z) continue;
        UNLINK( exit, first_wmapexit, last_wmapexit, next, prev );
        free(exit);
        save_exit = TRUE;
    }

    //tiles
    WMAPTILE_DATA *tile;
    for( tile = first_wmaptile; tile != NULL; tile = tile->next )
    {
        if(tile->x != x || tile->y != y || tile->z != z) continue;
        free_string(tile->symb);
        free_string(tile->name);
        free_string(tile->desc);
        tile->symb = str_dup("");
        tile->name = str_dup("");
        tile->desc = str_dup("");
        UNLINK( tile, first_wmaptile, last_wmaptile, next, prev );
        free(tile);
        save_tile = TRUE;
    }

    if(save_reset) save_wmap_resets(wmap_index);
    if(save_exit) save_wmap_exits();
    if(save_tile) save_wmap_tiles(wmap_index);
    send_to_char("Resets, exits, and tile data cleared.  Any changes saved.\r\n",ch);
    return TRUE;
}

//reloads the map from last saved PNG file
WEDIT (wedit_reload)
{
    int wmap_index = wmap_num(ch, NULL);

    if (wmap_index == -1)
    {
        send_to_char("You must be on a valid map to reload it.\r\n", ch);
        return FALSE;
    }
    load_wmap(wmap_index);
    send_to_char("Wmap reloaded.\r\n",ch);
    return TRUE;
}

-olc_save.c, at the top, add these includes:
#include "interp.h" //worldmap.c
#include "worldmap.h" //worldmap.c

-olc_save.c, in void save_object(), add these to the default list:
            fprintf (fp, "%s ", fwrite_flag (pObjIndex->value[5], buf)); //worldmap.c
            fprintf (fp, "%s\n", fwrite_flag (pObjIndex->value[6], buf)); //worldmap.c

-olc_save.c, in void do_asave(), in the spot that echoes syntax, add this under asave world:
            send_to_char
                ("  asave wmap     - saves the world map being edited\r\n", ch); //worldmap.c

-olc_save.c, in void do_asave(), at the bottom above the "show correct syntax" part, add:
    //worldmap.c
    /* Save worldmaps */
    /* ----------------------- */
    if (!str_cmp (arg1, "wmap"))
    {
        if(ch->desc->editor == ED_WMAP)
        {
            do_function(ch, &do_savemap, "");
            save_wmap_exits();
        }
        else
            send_to_char("You must be editing a worldmap for this.\r\n",ch);
        return;
    }


Step 7: Finishing Sector Flag mods, worldmap scan, look and display lists, string/color functions, memory
handling, movement, character saving/loading, and misc (act_info.c, act_move.c, asciimap.c, comm.c,
lookup.c, lookup.h, tables.c, recycle.c, save.c, scan.c, string.c)
-------
-act_info.c, in void show_list_to_char(), add the same_room check in the obj = list loop:
        if(!same_room(ch,NULL,obj)) continue; //worldmap.c

-act_info.c, in void show_char_to_char(), add the same_room check in the for loop:
        if(!same_room(ch,rch,NULL)) continue; //worldmap.c

-act_info.c, at the top of the file or just above the do_look() function, add:
extern void display_wmap args((CHAR_DATA *ch, bool alook)); //worldmap.c

-act_info.c, in do_look, we will be making two changes.  The first involves adding a "screenread" argument
  along with the "auto" or blank argument, adding the check for being on the map, and wrapping the
  existing auto look code into an else statement if not on the map.  The following code should copy/paste,
  but it contains color codes and other stuff specific to StockMUD.  Change or simply use as a reference
  as needed:
    if (arg1[0] == '\0' || !str_cmp (arg1, "auto") || !str_cmp (arg1, "screenread"))
    {
        if(!IS_NPC(ch) && is_wmap(ch,NULL)) //worldmap.c
        {
            if(!str_cmp (arg1, "screenread"))
                display_wmap(ch, FALSE);
            else
                display_wmap(ch, TRUE);
        }
        else
        {
            send_to_char ("{D", ch);
            send_to_char (ch->in_room->name, ch);
            send_to_char ("{x", ch);

            if ((IS_IMMORTAL (ch)
                 && (IS_NPC (ch) || IS_SET (ch->act, PLR_HOLYLIGHT)))
                || IS_BUILDER (ch, ch->in_room->area))
            {
                sprintf (buf, "{r [{RRoom %d{r]{x", ch->in_room->vnum);
                send_to_char (buf, ch);
            }

            send_to_char ("\r\n", ch);
            if (arg1[0] == '\0'
                || (!IS_NPC (ch) && !IS_SET (ch->comm, COMM_BRIEF)))
            {
                send_to_char ("  ", ch);
                send_to_char ("{w", ch);
                send_to_char (ch->in_room->description, ch);
                send_to_char ("{x", ch);
            }

            if (!IS_NPC (ch) && IS_SET (ch->act, PLR_AUTOEXIT))
            {
                send_to_char ("\r\n", ch);
                do_function (ch, &do_exits, "auto");
            }
        }
        show_list_to_char (ch->in_room->contents, ch, FALSE, FALSE);
        show_char_to_char (ch->in_room->people, ch);
        return;
    }
-The other do_look change, add the same_room check in the obj for look checking room->contents:
        if (same_room(ch,NULL,obj) && can_see_obj (ch, obj)) //worldmap.c

-act_info.c, in void do_practice(), add the same_room check in the mob for loop that's looking for mobs
  flagged with ACT_PRACTICE:
            if(!same_room(ch,mob,NULL)) continue; //worldmap.c
-directly under that, add the same_room check in mob == NULL check:
if (mob == NULL || !same_room(ch,mob,NULL)) //worldmap.c


-act_move.c, add worldmap.h include:
#include "worldmap.h" //worldmap.c

-act_move.c, at the top in "char *const dir_name", after down add:
, "northeast", "southeast", "southwest", "northwest"

-act_move.c, delete or comment out "const sh_int movement_loss".  This is handled by the new sector table.

-act_move.c, in void move_char(), we are removing the bulk of the code and calling the movement functions
  that are included in worldmap.c.  If you haven't made large changes to your move_char function, it might
  be easier to replace your entire function with this one:

void move_char (CHAR_DATA * ch, int door, bool follow)
{
    ROOM_INDEX_DATA *to_room;
    EXIT_DATA *pexit;

    if (door < DIR_NORTH || door > DIR_NORTHWEST)
    {
        bug ("Do_move: bad door %d.", door);
        return;
    }

    /*
     * Exit trigger, if activated, bail out. Only PCs are triggered.
     */
    if (!IS_NPC (ch) && mp_exit_trigger (ch, door))
        return;

    //worldmap.c
    if(is_wmap(ch,NULL))
    {
        if(!can_leave(ch,ch->in_room,TRUE))
            return;
        wmap_movement(ch,door,follow);
    }
    else
    {
        if (door > DIR_DOWN
            || (pexit = ch->in_room->exit[door]) == NULL
            || (to_room = pexit->u1.to_room) == NULL
            || !can_see_room (ch, pexit->u1.to_room))
        {
            send_to_char ("Alas, you cannot go that way.\r\n", ch);
            return;
        }

        if(!can_leave(ch,ch->in_room,FALSE)
        || !can_enter(ch,to_room,FALSE,-1,-1))
            return;

        room_movement(ch,door,pexit,to_room,follow);
    }

    if(!IS_NPC(ch) && !IS_HOLYLIGHT(ch))
        WAIT_STATE (ch, 1);

    /* 
     * If someone is following the char, these triggers get activated
     * for the followers before the char, but it's safer this way...
     */
    if (IS_NPC (ch) && HAS_TRIGGER (ch, TRIG_ENTRY))
        mp_percent_trigger (ch, NULL, NULL, NULL, TRIG_ENTRY);
    if (!IS_NPC (ch))
        mp_greet_trigger (ch);

    return;
}

-act_move.c, find void do_down() and paste this under:
//worldmap.c
void do_northeast (CHAR_DATA * ch, char *argument)
{
    move_char (ch, DIR_NORTHEAST, FALSE);
    return;
}

void do_northwest (CHAR_DATA * ch, char *argument)
{
    move_char (ch, DIR_NORTHWEST, FALSE);
    return;
}

void do_southeast (CHAR_DATA * ch, char *argument)
{
    move_char (ch, DIR_SOUTHEAST, FALSE);
    return;
}

void do_southwest (CHAR_DATA * ch, char *argument)
{
    move_char (ch, DIR_SOUTHWEST, FALSE);
    return;
}

-act_move.c, in void do_pick(), you are adding the same_room check as shown:
    /* look for guards */
    for (gch = ch->in_room->people; gch; gch = gch->next_in_room)
    {
        if(!same_room(ch,gch,NULL)) continue; //worldmap.c
        if (IS_NPC (gch) && IS_AWAKE (gch) && ch->level + 5 < gch->level)
        {
            act ("$N is standing too close to the lock.",
                 ch, NULL, gch, TO_CHAR);
            return;
        }
    }

Later in the installation, you will be instructed on the many, many places a similar check will need to be
added.

-act_move.c, in void do_recall(), take note that if you ever allow players to recall to the world map,
  it will be necessary to set coordinates after char_to_room

-act_move.c, in void do_train, add the same_room check:
    /*
     * Check for trainer.
     */
    for (mob = ch->in_room->people; mob; mob = mob->next_in_room)
    {
        if(!same_room(ch,mob,NULL)) continue; //worldmap.c
        if (IS_NPC (mob) && IS_SET (mob->act, ACT_TRAIN))
            break;
    }

    if (mob == NULL || !same_room(ch,mob,NULL)) //worldmap.c
    {
        send_to_char ("You can't do that here.\r\n", ch);
        return;
    }


-asciimap.c, if you are using this code, replace the provided get_ascii function with this:
//worldmap.c
char * get_ascii (ROOM_INDEX_DATA * pRoom, bool fWall)
{
    if (pRoom == NULL) return " ";
    if (!fWall)
        return sector_flags[pRoom->sector_type].floor;
    else
        return sector_flags[pRoom->sector_type].wall;
    return " ";
}

-comm.c, in void stop_idling(), you are adding code on both sides of the char_from_room and
  char_to_room, as such:

    //worldmap.c
    int orig_wmap = ch->wmap[0];
    int orig_x = ch->wmap[1];
    int orig_y = ch->wmap[2];
    int orig_z = ch->wmap[3];

    char_from_room (ch);
    char_to_room (ch, ch->was_in_room);

    //worldmap.c
    ch->wmap[0] = orig_wmap;
    ch->wmap[1] = orig_x;
    ch->wmap[2] = orig_y;
    ch->wmap[3] = orig_z;

-comm.c, in void act_new(), add the same_room check:
    for (; to != NULL; to = to->next_in_room)
    {
        if ((!IS_NPC (to) && to->desc == NULL)
            || (IS_NPC (to) && (!HAS_TRIGGER (to, TRIG_ACT) || !same_room(ch,to,NULL) ))  //worldmap.c
            || to->position < min_pos)
            continue;

        if ((type == TO_CHAR) && to != ch)
            continue;
        if (type == TO_VICT && (to != vch || to == ch))
            continue;
        if (type == TO_ROOM && to == ch)
            continue;
        if (type == TO_ROOM && !same_room(ch,to,NULL))  //worldmap.c
            continue;
        if (type == TO_NOTVICT && (to == ch || to == vch))
            continue;
        if (type == TO_NOTVICT && (!same_room(ch,to,NULL) || !same_room(vch,to,NULL)))  //worldmap.c
            continue;

-lookup.c, at the bottom add:
//worldmap.c
int sector_lookup (const char *name)
{
    int sector;

    for (sector = 0; sector < SECT_MAX; sector++)
    {
        if (LOWER (name[0]) == LOWER (sector_flags[sector].name[0])
            && !str_prefix (name, sector_flags[sector].name))
            return sector;
    }

    return -1;
}

-lookup.h, add:
//worldmap.c
int         sector_lookup    args( (const char *name) );


-recycle.c, in CHAR_DATA *new_char(), add:
    //worldmap.c
    ch->wmap[0] = -1;  //map
    ch->wmap[1] = -1;  //x
    ch->wmap[2] = -1;  //y
    ch->wmap[3] = 0;   //z
    ch->reset_wmap[0] = -1;  //map
    ch->reset_wmap[1] = -1;  //x
    ch->reset_wmap[2] = -1;  //y
    ch->reset_wmap[3] = 0;  //z

-recycle.c, in PC_DATA *new_pcdata(), add:
    pcdata->doorbump[0]    = -1; //worldmap.c
    pcdata->doorbump[1]    = 0; //worldmap.c
    pcdata->wmap_sec    = -1; //worldmap.c


-save.c, in void fwrite_char(), add this under the spot for saving room data:
    //worldmap.c
    if(ch->wmap[1] >= 0 && ch->wmap[1] >= 0 && ch->wmap[2] >= 0)
        fprintf (fp, "Wmap %d %d %d %d\n", ch->wmap[0],ch->wmap[1],ch->wmap[2],ch->wmap[3]);

-save.c, in void fwrite_obj(), under cost where the obj value[] is saved, modify it as such:
    if (obj->value[0] != obj->pIndexData->value[0]
        || obj->value[1] != obj->pIndexData->value[1]
        || obj->value[2] != obj->pIndexData->value[2]
        || obj->value[3] != obj->pIndexData->value[3]
        || obj->value[4] != obj->pIndexData->value[4])
        fprintf (fp, "Val  %d %d %d %d %d %d %d\n",
                 obj->value[0], obj->value[1], obj->value[2], obj->value[3],
                 obj->value[4], obj->value[5], obj->value[6]); //worldmap.c

-save.c, in fread_char() under Wizn in case 'W', add:
                //worldmap.c
                if (!str_cmp (word, "Wmap"))
                {
                    ch->wmap[0] = fread_number (fp);
                    ch->wmap[1] = fread_number (fp);
                    ch->wmap[2] = fread_number (fp);
                    ch->wmap[3] = fread_number (fp);
                    fMatch = TRUE;
                    break;
                }

-save.c, in fread_obj() in case 'V', modify values as such:
                if (!str_cmp (word, "Val"))
                {
                    obj->value[0] = fread_number (fp);
                    obj->value[1] = fread_number (fp);
                    obj->value[2] = fread_number (fp);
                    obj->value[3] = fread_number (fp);
                    obj->value[4] = fread_number (fp);
                    obj->value[5] = fread_number (fp); //worldmap.c
                    obj->value[6] = fread_number (fp); //worldmap.c
                    fMatch = TRUE;
                    break;
                }


-scan.c, add the math.h and worldmap.h includes:
#include <math.h>  //worldmap.c
#include "worldmap.h" //worldmap.c

-scan.c, at the top, add the prototype for wmap_scan:
void wmap_scan args ((CHAR_DATA *ch)); //worldmap.c

-scan.c, in void do_scan(), adding the worldmap functionality:
void do_scan (CHAR_DATA * ch, char *argument)
{
    extern char *const dir_name[];
    char arg1[MAX_INPUT_LENGTH], buf[MAX_INPUT_LENGTH];
    ROOM_INDEX_DATA *scan_room;
    EXIT_DATA *pExit;
    sh_int door, depth;

    argument = one_argument (argument, arg1);

    if (arg1[0] == '\0' || !str_cmp(arg1,"screenread"))
    {
        if(str_cmp(arg1,"screenread"))
        {
            act ("$n looks all around.", ch, NULL, NULL, TO_ROOM);
            send_to_char ("Looking around you see:\r\n", ch);
        }
        if(is_wmap(ch,NULL))  //worldmap.c
            wmap_scan(ch);
        else
        {
            scan_list (ch->in_room, ch, 0, -1);

            for (door = 0; door < 6; door++)
            {
                if ((pExit = ch->in_room->exit[door]) != NULL)
                    scan_list (pExit->u1.to_room, ch, 1, door);
            }
        }
        return;
    }
    else if (!str_cmp (arg1, "n") || !str_cmp (arg1, "north"))
        door = 0;
    else if (!str_cmp (arg1, "e") || !str_cmp (arg1, "east"))
        door = 1;
    else if (!str_cmp (arg1, "s") || !str_cmp (arg1, "south"))
        door = 2;
    else if (!str_cmp (arg1, "w") || !str_cmp (arg1, "west"))
        door = 3;
    else if (!str_cmp (arg1, "u") || !str_cmp (arg1, "up"))
        door = 4;
    else if (!str_cmp (arg1, "d") || !str_cmp (arg1, "down"))
        door = 5;
    else
    {
        send_to_char ("Which way do you want to scan?\r\n", ch);
        return;
    }

    if(is_wmap(ch,NULL)) return; //worldmap.c

    act ("You peer intently $T.", ch, NULL, dir_name[door], TO_CHAR);
    act ("$n peers intently $T.", ch, NULL, dir_name[door], TO_ROOM);
    sprintf (buf, "Looking %s you see:\r\n", dir_name[door]);

    scan_room = ch->in_room;

    for (depth = 1; depth < 4; depth++)
    {
        if ((pExit = scan_room->exit[door]) != NULL)
        {
            scan_room = pExit->u1.to_room;
            scan_list (pExit->u1.to_room, ch, depth, door);
        }
    }
    return;
}

-scan.c, add at the bottom of the file:
//worldmap.c
void scan_wmap_tile (WMAPTILE_DATA *tile, CHAR_DATA * ch, sh_int depth, sh_int door)
{
    extern char *const dir_name[];
    extern char *const distance[];
    char buf[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH];

    buf[0] = '\0';

    strcat (buf,"{D");
    strcat (buf, tile->name ? strip_color(tile->name) : "Unknown");
    strcat (buf, ", ");
    sprintf (buf2, distance[depth], dir_name[door]);
    strcat (buf, buf2);
    strcat (buf, "{x\r\n");

    send_to_char (buf, ch);
    return;
}

//worldmap.c
double wmap_dist(int x1, int y1, int x2, int y2)
{
    return sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
}

//worldmap.c
int direction(int x1, int y1, int x2, int y2)
{
    int dx = x2 - x1;
    int dy = y2 - y1;

    if (dx == 0 && dy == 0)
        return -1;
    else
    {
        // Negate dy to account for the top-left origin grid system
        double angle = atan2(-dy, dx) * 180.0 / M_PI; // Convert from radians to degrees

        if (angle >= -22.5 && angle < 22.5)
            return DIR_EAST;
        else if (angle >= 22.5 && angle < 67.5)
            return DIR_NORTHEAST;
        else if (angle >= 67.5 && angle < 112.5)
            return DIR_NORTH;
        else if (angle >= 112.5 && angle < 157.5)
            return DIR_NORTHWEST;
        else if (angle >= 157.5 || angle < -157.5)
            return DIR_WEST;
        else if (angle >= -157.5 && angle < -112.5)
            return DIR_SOUTHWEST;
        else if (angle >= -112.5 && angle < -67.5)
            return DIR_SOUTH;
        else if (angle >= -67.5 && angle < -22.5)
            return DIR_SOUTHEAST;

        return -1;  // Default case, shouldn't happen
    }
}

//worldmap.c
void wmap_scan(CHAR_DATA *ch)
{
    CHAR_DATA *rch;
    int dst;
    int mod = 0;
    int x1 = wmap_x(ch,NULL);
    int y1 = wmap_y(ch,NULL);
    int z1 = wmap_z(ch,NULL);
    int depth = MAX_WMAP_SCAN;
    WMAPTILE_DATA *tile;

    #if defined (WMAP_SECT_VIS)
    int wmap_index = wmap_num(ch,NULL);
    if(!IS_HOLYLIGHT(ch) && sector_flags[get_sector(NULL,wmap_index,x1,y1)].move > 2)
        mod += sector_flags[get_sector(NULL,wmap_index,x1,y1)].move * 100 / 150;
    #endif

    #if defined (WMAP_WTHR_VIS)
    if(!IS_HOLYLIGHT(ch) && (weather_info.sky == SKY_RAINING || weather_info.sky == SKY_LIGHTNING))
        mod += depth / 4;
    #endif

    #if defined (WMAP_NIGHT_VIS)
    if(!IS_HOLYLIGHT(ch) && (weather_info.sunlight == SUN_SET || weather_info.sunlight == SUN_DARK))
        mod += depth / 2;
    #endif

    //search and print maptile locations first
    for( tile = first_wmaptile; tile != NULL; tile = tile->next )
    {
        if(x1 == tile->x && y1 == tile->y && z1 == tile->z) continue;
        if(z1 != tile->z || tile->vis == 0) continue;

        dst = wmap_dist(x1,y1,tile->x,tile->y);

        if(dst <= depth)
            scan_wmap_tile (tile, ch, UMAX(1,dst / 3), direction(x1,y1,tile->x,tile->y));
    }

    //characters within wmap_dist
    for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
    {
        if(ch == rch) continue;
        if(!can_see(ch,rch)) continue;
        if(same_room(ch,rch,NULL)) //worldmap.c
        {
            scan_char (rch, ch, 0, 1);
            continue;
        }

        dst = wmap_dist(x1,y1,wmap_x(rch,NULL),wmap_y(rch,NULL));

        #if defined (WMAP_SECT_HIDE)
        mod += sector_flags[get_sector(rch,0,0,0)].move / 2;
        #endif

        if(dst <= depth - mod)
            scan_char (rch, ch, UMAX(1,dst / 3), direction(x1,y1,wmap_x(rch,NULL),wmap_y(rch,NULL)));
    }
    return;
}


-string.c, add these functions.  These could probably be written better, but they are functional.
//worldmap.c
char *fade_color16(const char *string)
{
    if (!string)
    {
        return NULL;
    }

    size_t len = strlen(string);
    char *result = (char *)malloc(len + 1);

    if (!result)
    {
        return NULL;
    }

    size_t i, j = 0;
    for (i = 0; i < len; i++)
    {
        if (string[i] == '{' && isupper(string[i + 1]) && string[i + 1] != 'D')
        {
            result[j++] = '{';
            result[j++] = tolower(string[i + 1]);
            i++; 
        }
        else
        {
            result[j++] = string[i];
        }
    }

    result[j] = '\0';
    return result;
}

char *fade_color(const char *string, int fade)
{
    char buf[MAX_STRING_LENGTH];
    char *newstr;
    int count = 0;
    char temp;
    int r = 0, g = 0, b = 0;
    bool bg = FALSE;

    if(fade > 5)
        fade = 5;

    newstr = buf;
    while (*string && count < (MAX_STRING_LENGTH - 1))
    {
        temp = *string++;
        if (temp == '{')
        {
            temp = *string++;
            if (temp == '[')
            {
                temp = *string++;
                if (temp == 'F' || temp == 'f' || temp == 'B' || temp == 'b')
                {
                    if(temp == 'B' || temp == 'b')
                        bg = TRUE;
                    else
                        bg = FALSE;
                    r = 0;
                    g = 0;
                    b = 0;
                    temp = *string++;
                    if (temp == 'G' || temp == 'g')
                    {
                        buf[count++] = '{';
                        buf[count++] = '[';
                        buf[count++] = 'F';
                        buf[count++] = 'G';

                        temp = *string++;;
                        if(temp == '0')
                            g = 0;
                        else if(temp == '1')
                            g = 1;
                        else
                            g = 2;

                        temp = *string++;;
                        if(temp == '0')
                            b = 0;
                        else if(temp == '1')
                            b = 1;
                        else if(temp == '2')
                            b = 2;
                        else if(temp == '3')
                            b = 3;
                        else if(temp == '4')
                            b = 4;
                        else if(temp == '5')
                            b = 5;
                        else if(temp == '6')
                            b = 6;
                        else if(temp == '7')
                            b = 7;
                        else if(temp == '8')
                            b = 8;
                        else
                            b = 9;

                        if(fade == 5)
                        {
                            buf[count++] = '0';
                            buf[count++] = '2';
                        }
                        else
                        {
                            int sum = g * 10 + b;

                            if(fade == 1)
                            {
                                sum = sum * 83 / 100;

                                g = (sum / 10) % 10;
                                b = sum  % 10;
                            }
                            else if(fade == 2)
                            {
                                sum = sum * 66 / 100;

                                g = (sum / 10) % 10;
                                b = sum  % 10;
                            }
                            else if(fade == 3)
                            {
                                sum = sum * 49 / 100;

                                g = (sum / 10) % 10;
                                b = sum  % 10;
                            }
                            else if(fade == 4)
                            {
                                sum = sum * 32 / 100;

                                g = (sum / 10) % 10;
                                b = sum  % 10;
                            }


                            if(g == 2)
                                buf[count++] = '2';
                            else if(g == 1)
                                buf[count++] = '1';
                            else if(g == 0)
                                buf[count++] = '0';

                            if(b == 9)
                                buf[count++] = '9';
                            else if(b == 8)
                                buf[count++] = '8';
                            else if(b == 7)
                                buf[count++] = '7';
                            else if(b == 6)
                                buf[count++] = '6';
                            else if(b == 5)
                                buf[count++] = '5';
                            else if(b == 4)
                                buf[count++] = '4';
                            else if(b == 3)
                                buf[count++] = '3';
                            else if(b == 2)
                                buf[count++] = '2';
                            else if(b == 1)
                                buf[count++] = '1';
                            else if(b == 0)
                            {
                                if(g == 0)
                                    buf[count++] = '1';
                                else
                                    buf[count++] = '0';
                            }
                        }
                    }
                    else
                    {
                        buf[count++] = '{';
                        buf[count++] = '[';
                        if(!bg)
                            buf[count++] = 'F';
                        else
                            buf[count++] = 'B';

                        if(temp == '0')
                            r = 0;
                        else if(temp == '1')
                            r = 1;
                        else if(temp == '2')
                            r = 2;
                        else if(temp == '3')
                            r = 3;
                        else if(temp == '4')
                            r = 4;
                        else
                            r = 5;

                        temp = *string++;;
                        if(temp == '0')
                            g = 0;
                        else if(temp == '1')
                            g = 1;
                        else if(temp == '2')
                            g = 2;
                        else if(temp == '3')
                            g = 3;
                        else if(temp == '4')
                            g = 4;
                        else
                            g = 5;

                        temp = *string++;;
                        if(temp == '0')
                            b = 0;
                        else if(temp == '1')
                            b = 1;
                        else if(temp == '2')
                            b = 2;
                        else if(temp == '3')
                            b = 3;
                        else if(temp == '4')
                            b = 4;
                        else
                            b = 5;

                        if(fade == 5)
                        {
                            buf[count++] = 'G';
                            buf[count++] = '0';
                            buf[count++] = '2';
                        }
                        else
                        {
                            if(fade == 1)
                            {
                                if(r > 2)
                                    r -= 1;
                                if(g > 2)
                                    g -= 1;
                                if(b > 2)
                                    b -= 1;
                            }
                            else if(fade == 2)
                            {
                                if(r == 0)
                                    r = 0;
                                else if(r == 1)
                                    r = 1;
                                else if(r == 2)
                                    r -= 1;
                                else
                                    r -= fade;

                                if(g == 0)
                                    g = 0;
                                else if(g == 1)
                                    g = 1;
                                else if(g == 2)
                                    g -= 1;
                                else
                                    g -= fade;

                                if(b == 0)
                                    b = 0;
                                else if(b == 1)
                                    b = 1;
                                else if(b == 2)
                                    b -= 1;
                                else
                                    b -= fade;
                            }
                            else if(fade == 3)
                            {
                                if(r == 0)
                                    r = 0;
                                else if(r == 1)
                                    r = 1;
                                else if(r == 2)
                                    r -= 1;
                                else if(r == 3)
                                    r -= 2;
                                else
                                    r -= fade;

                                if(g == 0)
                                    g = 0;
                                else if(g == 1)
                                    g = 1;
                                else if(g == 2)
                                    g -= 1;
                                else if(g == 3)
                                    g -= 2;
                                else
                                    g -= fade;

                                if(b == 0)
                                    b = 0;
                                else if(b == 1)
                                    b = 1;
                                else if(b == 2)
                                    b -= 1;
                                else if(b == 3)
                                    b -= 2;
                                else
                                    b -= fade;
                            }
                            else if(fade == 4)
                            {
                                if(r > 0)
                                    r = 1;
                                if(g > 0)
                                    g = 1;
                                if(b > 0)
                                    b = 1;
                            }

                            if(r == 5)
                                buf[count++] = '5';
                            else if(r == 4)
                                buf[count++] = '4';
                            else if(r == 3)
                                buf[count++] = '3';
                            else if(r == 2)
                                buf[count++] = '2';
                            else if(r == 1)
                                buf[count++] = '1';
                            else if(r == 0)
                                buf[count++] = '0';

                            if(g == 5)
                                buf[count++] = '5';
                            else if(g == 4)
                                buf[count++] = '4';
                            else if(g == 3)
                                buf[count++] = '3';
                            else if(g == 2)
                                buf[count++] = '2';
                            else if(g == 1)
                                buf[count++] = '1';
                            else if(g == 0)
                                buf[count++] = '0';

                            if(b == 5)
                                buf[count++] = '5';
                            else if(b == 4)
                                buf[count++] = '4';
                            else if(b == 3)
                                buf[count++] = '3';
                            else if(b == 2)
                                buf[count++] = '2';
                            else if(b == 1)
                                buf[count++] = '1';
                            else if(b == 0)
                                buf[count++] = '0';
                        }

                    }
                    //buf[count++] = ']';
                }
            }
            else if (temp == '{')
            {
                buf[count++] = '{';
                buf[count++] = temp;
            }
            else
            {
                buf[count++] = '{';

                if (temp == 'r' || temp == 'R' || temp == 'g' || temp == 'G' || temp == 'y' || temp == 'Y' || temp == 'b' || temp == 'B'
                ||  temp == 'm' || temp == 'M' || temp == 'c' || temp == 'C' || temp == 'w' || temp == 'W' || temp == 'a' || temp == 'A'
                ||  temp == 'j' || temp == 'J' || temp == 'l' || temp == 'L' || temp == 'o' || temp == 'O' || temp == 'p' || temp == 'P'
                ||  temp == 't' || temp == 'T' || temp == 'v' || temp == 'V' || temp == 'D')
                {
                    r = 0;
                    g = 0;
                    b = 0;
                    buf[count++] = '[';
                    buf[count++] = 'F';

                    if(fade == 5)
                    {
                        buf[count++] = 'G';
                        buf[count++] = '0';
                        buf[count++] = '2';
                        buf[count++] = ']';
                    }
                    else
                    {
                        switch ( temp )
                        {
                            case 'r': // dark red F200
                                r = 2; g = 0; b = 0;
                                break;
                            case 'R': // light red F500
                                r = 5; g = 0; b = 0;
                                break;
                            case 'g': // dark green F020
                                r = 0; g = 2; b = 0;
                                break;
                            case 'G': // light green F050
                                r = 0; g = 5; b = 0;
                                break;
                            case 'y': // dark yellow F220
                                r = 2; g = 2; b = 0;
                                break;
                            case 'Y': // light yellow F550
                                r = 5; g = 5; b = 0;
                                break;
                            case 'b': // dark blue F002
                                r = 0; g = 0; b = 2;
                                break;
                            case 'B': // light blue F005
                                r = 0; g = 0; b = 5;
                                break;
                            case 'm': // dark magenta F202
                                r = 2; g = 0; b = 2;
                                break;
                            case 'M': // light magenta F505
                                r = 5; g = 0; b = 5;
                                break;
                            case 'c': // dark cyan F022
                                r = 0; g = 2; b = 2;
                                break;
                            case 'C': // light cyan F055
                                r = 0; g = 5; b = 5;
                                break;
                            case 'w': // dark white F333
                                r = 3; g = 3; b = 3;
                                break;
                            case 'W': // light white F555
                                r = 5; g = 5; b = 5;
                                break;
                            case 'a': // dark azure F014
                                r = 0; g = 1; b = 4;
                                break;
                            case 'A': // light azure F025
                                r = 0; g = 2; b = 5;
                                break;
                            case 'j': // dark jade F031
                                r = 0; g = 3; b = 1;
                                break;
                            case 'J': // light jade F052
                                r = 0; g = 5; b = 2;
                                break;
                            case 'l': // dark lime F140
                                r = 1; g = 4; b = 0;
                                break;
                            case 'L': // light lime F250
                                r = 2; g = 5; b = 0;
                                break;
                            case 'o': // dark orange F310
                                r = 3; g = 1; b = 0;
                                break;
                            case 'O': // light orange F520
                                r = 5; g = 2; b = 0;
                                break;
                            case 'p': // dark pink F301
                                r = 3; g = 0; b = 1;
                                break;
                            case 'P': // light pink F502
                                r = 5; g = 0; b = 2;
                                break;
                            case 't': // dark tan F210
                                r = 2; g = 1; b = 0;
                                break;
                            case 'T': // light tan F321
                                r = 3; g = 2; b = 1;
                                break;
                            case 'v': // dark violet F104
                                r = 1; g = 0; b = 4;
                                break;
                            case 'V': // light violet F205
                                r = 2; g = 0; b = 5;
                                break;
                        }

                        if(temp == 'D')
                        {
                            buf[count++] = 'G';
                            if(fade == 1)
                            {
                                buf[count++] = '1';
                                buf[count++] = '0';
                            }
                            else if(fade == 2)
                            {
                                buf[count++] = '0';
                                buf[count++] = '8';
                            }
                            else if(fade == 3)
                            {
                                buf[count++] = '0';
                                buf[count++] = '6';
                            }
                            else
                            {
                                buf[count++] = '0';
                                buf[count++] = '4';
                            }
                        }
                        else
                        {
                            if(fade == 1)
                            {
                                if(r > 2)
                                    r -= 1;
                                if(g > 2)
                                    g -= 1;
                                if(b > 2)
                                    b -= 1;
                            }
                            else if(fade == 2)
                            {
                                if(r == 0)
                                    r = 0;
                                else if(r == 1)
                                    r = 1;
                                else if(r == 2)
                                    r -= 1;
                                else
                                    r -= fade;

                                if(g == 0)
                                    g = 0;
                                else if(g == 1)
                                    g = 1;
                                else if(g == 2)
                                    g -= 1;
                                else
                                    g -= fade;

                                if(b == 0)
                                    b = 0;
                                else if(b == 1)
                                    b = 1;
                                else if(b == 2)
                                    b -= 1;
                                else
                                    b -= fade;
                            }
                            else if(fade == 3)
                            {
                                if(r == 0)
                                    r = 0;
                                else if(r == 1)
                                    r = 1;
                                else if(r == 2)
                                    r -= 1;
                                else if(r == 3)
                                    r -= 2;
                                else
                                    r -= fade;

                                if(g == 0)
                                    g = 0;
                                else if(g == 1)
                                    g = 1;
                                else if(g == 2)
                                    g -= 1;
                                else if(g == 3)
                                    g -= 2;
                                else
                                    g -= fade;

                                if(b == 0)
                                    b = 0;
                                else if(b == 1)
                                    b = 1;
                                else if(b == 2)
                                    b -= 1;
                                else if(b == 3)
                                    b -= 2;
                                else
                                    b -= fade;
                            }
                            else if(fade == 4)
                            {
                                if(r > 0)
                                    r = 1;
                                if(g > 0)
                                    g = 1;
                                if(b > 0)
                                    b = 1;
                            }

                            if(r == 5)
                                buf[count++] = '5';
                            else if(r == 4)
                                buf[count++] = '4';
                            else if(r == 3)
                                buf[count++] = '3';
                            else if(r == 2)
                                buf[count++] = '2';
                            else if(r == 1)
                                buf[count++] = '1';
                            else if(r == 0)
                                buf[count++] = '0';

                            if(g == 5)
                                buf[count++] = '5';
                            else if(g == 4)
                                buf[count++] = '4';
                            else if(g == 3)
                                buf[count++] = '3';
                            else if(g == 2)
                                buf[count++] = '2';
                            else if(g == 1)
                                buf[count++] = '1';
                            else if(g == 0)
                                buf[count++] = '0';

                            if(b == 5)
                                buf[count++] = '5';
                            else if(b == 4)
                                buf[count++] = '4';
                            else if(b == 3)
                                buf[count++] = '3';
                            else if(b == 2)
                                buf[count++] = '2';
                            else if(b == 1)
                                buf[count++] = '1';
                            else if(b == 0)
                                buf[count++] = '0';
                        }

                        buf[count++] = ']';
                    }
                }
                else
                    buf[count++] = temp;
            }
            continue;
        }
        buf[count++] = temp;
    }
    buf[count] = '\0';
    return newstr;
}

char *bright_color16(const char *string)
{
    if (!string)
    {
        return NULL;
    }

    size_t len = strlen(string);
    char *result = (char *)malloc(len + 1);

    if (!result)
    {
        return NULL;
    }

    size_t i, j = 0;
    for (i = 0; i < len; i++)
    {
        if (string[i] == '{' && string[i + 1] == 'D')
        {
            result[j++] = '{';
            result[j++] = 'w';
            i++; 
        }
        else if (string[i] == '{' && islower(string[i + 1]))
        {
            result[j++] = '{';
            result[j++] = toupper(string[i + 1]);
            i++; 
        }
        else
        {
            result[j++] = string[i];
        }
    }

    result[j] = '\0';
    return result;
}

char *bright_color(const char *string, int fade)
{
    char buf[MAX_STRING_LENGTH];
    char *newstr;
    int count = 0;
    char temp;
    int r = 0, g = 0, b = 0;
    bool bg = FALSE;

    if(fade > 5)
        fade = 5;

    newstr = buf;
    while (*string && count < (MAX_STRING_LENGTH - 1))
    {
        temp = *string++;
        if (temp == '{')
        {
            temp = *string++;
            if (temp == '[')
            {
                temp = *string++;
                if (temp == 'F' || temp == 'f' || temp == 'B' || temp == 'b')
                {
                    if(temp == 'B' || temp == 'b')
                        bg = TRUE;
                    else
                        bg = FALSE;
                    r = 0;
                    g = 0;
                    b = 0;
                    temp = *string++;
                    if (temp == 'G' || temp == 'g')
                    {
                        buf[count++] = '{';
                        buf[count++] = '[';
                        buf[count++] = 'F';
                        buf[count++] = 'G';

                        temp = *string++;;
                        if(temp == '0')
                            g = 0;
                        else if(temp == '1')
                            g = 1;
                        else
                            g = 2;

                        temp = *string++;;
                        if(temp == '0')
                            b = 0;
                        else if(temp == '1')
                            b = 1;
                        else if(temp == '2')
                            b = 2;
                        else if(temp == '3')
                            b = 3;
                        else if(temp == '4')
                            b = 4;
                        else if(temp == '5')
                            b = 5;
                        else if(temp == '6')
                            b = 6;
                        else if(temp == '7')
                            b = 7;
                        else if(temp == '8')
                            b = 8;
                        else
                            b = 9;

                        if(fade == 5)
                        {
                            buf[count++] = '2';
                            buf[count++] = '4';
                        }
                        else
                        {
                            int sum = g * 10 + b;

                            if(fade == 1)
                            {
                                sum += 4;
                                if(sum > 23)
                                    sum = 23;
                                g = (sum / 10) % 10;
                                b = sum  % 10;
                            }
                            else if(fade == 2)
                            {
                                sum += 8;
                                if(sum > 23)
                                    sum = 23;
                                g = (sum / 10) % 10;
                                b = sum  % 10;
                            }
                            else if(fade == 3)
                            {
                                sum += 12;
                                if(sum > 23)
                                    sum = 23;
                                g = (sum / 10) % 10;
                                b = sum  % 10;
                            }
                            else if(fade == 4)
                            {
                                sum += 12;
                                if(sum > 23)
                                    sum = 23;
                                g = (sum / 10) % 10;
                                b = sum  % 10;
                            }

                            if(g >= 2)
                                buf[count++] = '2';
                            else if(g == 1)
                                buf[count++] = '1';
                            else if(g <= 0)
                                buf[count++] = '0';

                            if(b >= 9)
                            {
                                if(g == 2)
                                    buf[count++] = '4';
                                else
                                    buf[count++] = '9';
                            }
                            else if(b == 8)
                            {
                                if(g == 2)
                                    buf[count++] = '4';
                                else
                                    buf[count++] = '8';
                            }
                            else if(b == 7)
                            {
                                if(g == 2)
                                    buf[count++] = '4';
                                else
                                    buf[count++] = '7';
                            }
                            else if(b == 6)
                            {
                                if(g == 2)
                                    buf[count++] = '4';
                                else
                                    buf[count++] = '6';
                            }
                            else if(b == 5)
                            {
                                if(g == 2)
                                    buf[count++] = '4';
                                else
                                    buf[count++] = '5';
                            }
                            else if(b == 4)
                                buf[count++] = '4';
                            else if(b == 3)
                                buf[count++] = '3';
                            else if(b == 2)
                                buf[count++] = '2';
                            else if(b == 1)
                                buf[count++] = '1';
                            else if(b <= 0)
                                buf[count++] = '0';
                        }
                    }
                    else
                    {
                        buf[count++] = '{';
                        buf[count++] = '[';
                        if(!bg)
                            buf[count++] = 'F';
                        else
                            buf[count++] = 'B';

                        if(temp == '0')
                            r = 0;
                        else if(temp == '1')
                            r = 1;
                        else if(temp == '2')
                            r = 2;
                        else if(temp == '3')
                            r = 3;
                        else if(temp == '4')
                            r = 4;
                        else
                            r = 5;

                        temp = *string++;;
                        if(temp == '0')
                            g = 0;
                        else if(temp == '1')
                            g = 1;
                        else if(temp == '2')
                            g = 2;
                        else if(temp == '3')
                            g = 3;
                        else if(temp == '4')
                            g = 4;
                        else
                            g = 5;

                        temp = *string++;;
                        if(temp == '0')
                            b = 0;
                        else if(temp == '1')
                            b = 1;
                        else if(temp == '2')
                            b = 2;
                        else if(temp == '3')
                            b = 3;
                        else if(temp == '4')
                            b = 4;
                        else
                            b = 5;

                        if(fade == 5)
                        {
                            buf[count++] = '5';
                            buf[count++] = '5';
                            buf[count++] = '5';
                        }
                        else
                        {
                            if(fade == 1)
                            {
                                if(r < 3)
                                    r += 1;
                                if(g < 3)
                                    g += 1;
                                if(b < 3)
                                    b += 1;
                            }
                            else if(fade == 2)
                            {
                                if(r == 5)
                                    r = 5;
                                else if(r == 4)
                                    r = 4;
                                else if(r == 3)
                                    r += 1;
                                else
                                    r += fade;

                                if(g == 5)
                                    g = 5;
                                else if(g == 4)
                                    g = 4;
                                else if(g == 3)
                                    g += 1;
                                else
                                    g += fade;

                                if(b == 5)
                                    b = 5;
                                else if(b == 4)
                                    b = 4;
                                else if(b == 3)
                                    b += 1;
                                else
                                    b += fade;
                            }
                            else if(fade == 3)
                            {
                                if(r == 5)
                                    r = 5;
                                else if(r == 4)
                                    r = 4;
                                else if(r == 3)
                                    r += 1;
                                else if(r == 2)
                                    r += 2;
                                else
                                    r += fade;

                                if(g == 5)
                                    g = 5;
                                else if(g == 4)
                                    g = 4;
                                else if(g == 3)
                                    g += 1;
                                else if(g == 2)
                                    g += 2;
                                else
                                    g += fade;

                                if(b == 5)
                                    b = 5;
                                else if(b == 4)
                                    b = 4;
                                else if(b == 3)
                                    b += 1;
                                else if(b == 2)
                                    b += 2;
                                else
                                    b += fade;
                            }
                            else if(fade == 4)
                            {
                                if(r < 5)
                                    r = 4;
                                if(g < 5)
                                    g = 4;
                                if(b < 5)
                                    b = 4;
                            }

                            if(r == 5)
                                buf[count++] = '5';
                            else if(r == 4)
                                buf[count++] = '4';
                            else if(r == 3)
                                buf[count++] = '3';
                            else if(r == 2)
                                buf[count++] = '2';
                            else if(r == 1)
                                buf[count++] = '1';
                            else if(r == 0)
                                buf[count++] = '0';

                            if(g == 5)
                                buf[count++] = '5';
                            else if(g == 4)
                                buf[count++] = '4';
                            else if(g == 3)
                                buf[count++] = '3';
                            else if(g == 2)
                                buf[count++] = '2';
                            else if(g == 1)
                                buf[count++] = '1';
                            else if(g == 0)
                                buf[count++] = '0';

                            if(b == 5)
                                buf[count++] = '5';
                            else if(b == 4)
                                buf[count++] = '4';
                            else if(b == 3)
                                buf[count++] = '3';
                            else if(b == 2)
                                buf[count++] = '2';
                            else if(b == 1)
                                buf[count++] = '1';
                            else if(b == 0)
                                buf[count++] = '0';
                        }

                    }
                    //buf[count++] = ']';
                }
            }
            else if (temp == '{')
            {
                buf[count++] = '{';
                buf[count++] = temp;
            }
            else
            {
                buf[count++] = '{';

                if (temp == 'r' || temp == 'R' || temp == 'g' || temp == 'G' || temp == 'y' || temp == 'Y' || temp == 'b' || temp == 'B'
                ||  temp == 'm' || temp == 'M' || temp == 'c' || temp == 'C' || temp == 'w' || temp == 'W' || temp == 'a' || temp == 'A'
                ||  temp == 'j' || temp == 'J' || temp == 'l' || temp == 'L' || temp == 'o' || temp == 'O' || temp == 'p' || temp == 'P'
                ||  temp == 't' || temp == 'T' || temp == 'v' || temp == 'V' || temp == 'D')
                {
                    r = 0;
                    g = 0;
                    b = 0;
                    buf[count++] = '[';
                    buf[count++] = 'F';

                    if(fade == 5)
                    {
                        buf[count++] = '5';
                        buf[count++] = '5';
                        buf[count++] = '5';
                        buf[count++] = ']';
                    }
                    else
                    {
                        switch ( temp )
                        {
                            case 'r': // dark red F200
                                r = 2; g = 0; b = 0;
                                break;
                            case 'R': // light red F500
                                r = 5; g = 0; b = 0;
                                break;
                            case 'g': // dark green F020
                                r = 0; g = 2; b = 0;
                                break;
                            case 'G': // light green F050
                                r = 0; g = 5; b = 0;
                                break;
                            case 'y': // dark yellow F220
                                r = 2; g = 2; b = 0;
                                break;
                            case 'Y': // light yellow F550
                                r = 5; g = 5; b = 0;
                                break;
                            case 'b': // dark blue F002
                                r = 0; g = 0; b = 2;
                                break;
                            case 'B': // light blue F005
                                r = 0; g = 0; b = 5;
                                break;
                            case 'm': // dark magenta F202
                                r = 2; g = 0; b = 2;
                                break;
                            case 'M': // light magenta F505
                                r = 5; g = 0; b = 5;
                                break;
                            case 'c': // dark cyan F022
                                r = 0; g = 2; b = 2;
                                break;
                            case 'C': // light cyan F055
                                r = 0; g = 5; b = 5;
                                break;
                            case 'w': // dark white F333
                                r = 3; g = 3; b = 3;
                                break;
                            case 'W': // light white F555
                                r = 5; g = 5; b = 5;
                                break;
                            case 'a': // dark azure F014
                                r = 0; g = 1; b = 4;
                                break;
                            case 'A': // light azure F025
                                r = 0; g = 2; b = 5;
                                break;
                            case 'j': // dark jade F031
                                r = 0; g = 3; b = 1;
                                break;
                            case 'J': // light jade F052
                                r = 0; g = 5; b = 2;
                                break;
                            case 'l': // dark lime F140
                                r = 1; g = 4; b = 0;
                                break;
                            case 'L': // light lime F250
                                r = 2; g = 5; b = 0;
                                break;
                            case 'o': // dark orange F310
                                r = 3; g = 1; b = 0;
                                break;
                            case 'O': // light orange F520
                                r = 5; g = 2; b = 0;
                                break;
                            case 'p': // dark pink F301
                                r = 3; g = 0; b = 1;
                                break;
                            case 'P': // light pink F502
                                r = 5; g = 0; b = 2;
                                break;
                            case 't': // dark tan F210
                                r = 2; g = 1; b = 0;
                                break;
                            case 'T': // light tan F321
                                r = 3; g = 2; b = 1;
                                break;
                            case 'v': // dark violet F104
                                r = 1; g = 0; b = 4;
                                break;
                            case 'V': // light violet F205
                                r = 2; g = 0; b = 5;
                                break;
                        }

                        if(temp == 'D')
                        {
                            buf[count++] = 'G';
                            if(fade == 1)
                            {
                                buf[count++] = '1';
                                buf[count++] = '4';
                            }
                            else if(fade == 2)
                            {
                                buf[count++] = '1';
                                buf[count++] = '6';
                            }
                            else if(fade == 3)
                            {
                                buf[count++] = '1';
                                buf[count++] = '8';
                            }
                            else
                            {
                                buf[count++] = '2';
                                buf[count++] = '0';
                            }
                        }
                        else
                        {
                            if(fade == 1)
                            {
                                if(r < 3)
                                    r += 1;
                                if(g < 3)
                                    g += 1;
                                if(b < 3)
                                    b += 1;
                            }
                            else if(fade == 2)
                            {
                                if(r == 5)
                                    r = 5;
                                else if(r == 4)
                                    r = 4;
                                else if(r == 3)
                                    r += 1;
                                else
                                    r += fade;

                                if(g == 5)
                                    g = 5;
                                else if(g == 4)
                                    g = 4;
                                else if(g == 3)
                                    g += 1;
                                else
                                    g += fade;

                                if(b == 5)
                                    b = 5;
                                else if(b == 4)
                                    b = 4;
                                else if(b == 3)
                                    b += 1;
                                else
                                    b += fade;
                            }
                            else if(fade == 3)
                            {
                                if(r == 5)
                                    r = 5;
                                else if(r == 4)
                                    r = 4;
                                else if(r == 3)
                                    r += 1;
                                else if(r == 2)
                                    r += 2;
                                else
                                    r += fade;

                                if(g == 5)
                                    g = 5;
                                else if(g == 4)
                                    g = 4;
                                else if(g == 3)
                                    g += 1;
                                else if(g == 2)
                                    g += 2;
                                else
                                    g += fade;

                                if(b == 5)
                                    b = 5;
                                else if(b == 4)
                                    b = 4;
                                else if(b == 3)
                                    b += 1;
                                else if(b == 2)
                                    b += 2;
                                else
                                    b += fade;
                            }
                            else if(fade == 4)
                            {
                                if(r < 5)
                                    r = 4;
                                if(g < 5)
                                    g = 4;
                                if(b < 5)
                                    b = 4;
                            }

                            if(r == 5)
                                buf[count++] = '5';
                            else if(r == 4)
                                buf[count++] = '4';
                            else if(r == 3)
                                buf[count++] = '3';
                            else if(r == 2)
                                buf[count++] = '2';
                            else if(r == 1)
                                buf[count++] = '1';
                            else if(r == 0)
                                buf[count++] = '0';

                            if(g == 5)
                                buf[count++] = '5';
                            else if(g == 4)
                                buf[count++] = '4';
                            else if(g == 3)
                                buf[count++] = '3';
                            else if(g == 2)
                                buf[count++] = '2';
                            else if(g == 1)
                                buf[count++] = '1';
                            else if(g == 0)
                                buf[count++] = '0';

                            if(b == 5)
                                buf[count++] = '5';
                            else if(b == 4)
                                buf[count++] = '4';
                            else if(b == 3)
                                buf[count++] = '3';
                            else if(b == 2)
                                buf[count++] = '2';
                            else if(b == 1)
                                buf[count++] = '1';
                            else if(b == 0)
                                buf[count++] = '0';
                        }

                        buf[count++] = ']';
                    }
                }
                else
                    buf[count++] = temp;
            }
            continue;
        }
        buf[count++] = temp;
    }
    buf[count] = '\0';
    return newstr;
}

char *strip_newlines(const char *string)
{
    if (!string)
        return NULL;

    size_t len = strlen(string);
    char *result = (char *)malloc(len + 1);

    if (!result)
        return NULL;

    size_t i, j = 0;
    for (i = 0; i < len; i++)
    {
        if (string[i] == '\n' || string[i] == '\r')
        {
            result[j++] = ' ';
            
            // Skip the next character if it's also a newline type to avoid double spaces
            if (string[i + 1] == '\n' || string[i + 1] == '\r')
                i++;
        }
        else
            result[j++] = string[i];
    }

    result[j] = '\0';
    return result;
}


-tables.c, either delete or comment out the const struct flag_type sector_flags table.


Step 8: enter, goto, transfer, at, and mob goto / transfer / at, act_enter.c act_wiz.c, mob_cmds.c
-------
-act_enter.c:
ROOM_INDEX_DATA *get_random_room (CHAR_DATA * ch)
{
    ROOM_INDEX_DATA *room;

    for (;;)
    {
        room = get_room_index (number_range (0, 65535));
        if (room != NULL)
            if (can_see_room (ch, room)
                && !is_wmap_vnum(room->vnum) //worldmap.c
                && !room_is_private (room)
                && !IS_SET (room->room_flags, ROOM_PRIVATE)
                && !IS_SET (room->room_flags, ROOM_SOLITARY)
                && !IS_SET (room->room_flags, ROOM_SAFE)
                && (IS_NPC (ch) || IS_SET (ch->act, ACT_AGGRESSIVE)
                    || !IS_SET (room->room_flags, ROOM_LAW)))
                break;
    }

    return room;
}

-act_enter.c: in do_enter, add this after char_to_room:
        //worldmap.c
        if(is_wmap_vnum(location->vnum) && portal->value[4] >= 0 && portal->value[5] >= 0 && portal->value[6] >= 0)
        {
            set_x(ch,NULL,portal->value[5]);
            set_y(ch,NULL,portal->value[6]);
            set_wmap(ch,NULL,portal->value[4]);
        }

-act_enter.c: below that, clone coords after obj_to_room:
        if (IS_SET (portal->value[2], GATE_GOWITH))
        {                        /* take the gate along */
            obj_from_room (portal);
            obj_to_room (portal, location);
            clone_coords(NULL,portal,ch,NULL); //worldmap.c
        }

-act_enter.c: further down in the for loop checking followers, right under the portal == NULL check:
if(!same_room(ch,fch,NULL)) continue; //worldmap.c


-act_wiz.c, add the worldmap.h include:
#include "worldmap.h" //worldmap.c

-act_wiz.c, in void do_smote(), add the same_room check:
    for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
    {
        if (vch->desc == NULL || vch == ch)
            continue;

        if(!same_room(ch,vch,NULL)) continue; //worldmap.c

-act_wiz.c, in ROOM_INDEX_DATA *find_location(), add this under the is_number check:
    //worldmap.c
    for (int i = 0; i < MAX_WMAP; i++)
    {
        if (!str_cmp(arg,wmap_table[i].name))
            return get_room_index(wmap_table[i].vnum);
    }

-act_wiz.c, in void do_transfer(), make the listed additions/changes:
void do_transfer (CHAR_DATA * ch, char *argument)
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char arg_x[MAX_INPUT_LENGTH];  //worldmap.c
    char arg_y[MAX_INPUT_LENGTH];  //worldmap.c
    int mp_x = -1;  //worldmap.c
    int mp_y = -1;  //worldmap.c
    ROOM_INDEX_DATA *location = NULL;  //worldmap.c -- add = NULL
    DESCRIPTOR_DATA *d;
    CHAR_DATA *victim;

    argument = one_argument (argument, arg1);
    argument = one_argument (argument, arg2);
    argument = one_argument (argument, arg_x); //worldmap.c
    argument = one_argument (argument, arg_y); //worldmap.c

    if (arg1[0] == '\0')
    {
        send_to_char ("Transfer whom (and where)?\r\n", ch);
        return;
    }

    if (!str_cmp (arg1, "all"))
    {
        for (d = descriptor_list; d != NULL; d = d->next)
        {
            if (d->connected == CON_PLAYING
                && d->character != ch
                && d->character->in_room != NULL
                && can_see (ch, d->character))
            {
                char buf[MAX_STRING_LENGTH];
                sprintf (buf, "%s %s %s %s", d->character->name, arg2, arg_x, arg_y); //worldmap.c
                do_function (ch, &do_transfer, buf);
            }
        }
        return;
    }

    //worldmap.c -- move the victim checks from below to up here
    if ((victim = get_char_world (ch, arg1)) == NULL)
    {
        send_to_char ("They aren't here.\r\n", ch);
        return;
    }

    if (victim->in_room == NULL)
    {
        send_to_char ("They are in limbo.\r\n", ch);
        return;
    }

    /*
     * Thanks to Grodyn for the optional location parameter.
     */
    if (arg2[0] == '\0')
    {
        location = ch->in_room;
        if(is_wmap_vnum(location->vnum))
        {
            mp_x = wmap_x(ch,NULL);
            mp_y = wmap_y(ch,NULL);
        }
    }

    else if(!str_prefix(arg2,"coordinates")) //worldmap.c
    {
        if(!is_wmap(victim,NULL))
        {
            send_to_char("This only works on the world map.  Transfer there first!\r\n",ch);
            return;
        }

        if(!is_number(arg_x) || !is_number(arg_y))
        {
            send_to_char("Syntax: transfer <victim> coordinates <#> <#>\r\n"
                                  transfer <victim> <#> <#>\r\n",ch);
            return;
        }
        mp_x = atoi(arg_x);
        mp_y = atoi(arg_y);

        if(mp_x < 0 || mp_y < 0 || mp_x > wmax_x(ch) || mp_y > wmax_y(ch))
        {
            send_to_char("Coordinates cannot exceed map's limits.\r\n",ch);
            return;
        }
        location = victim->in_room;
    }

    else if (is_number(arg2) && is_number(arg_x) && arg_y[0] == '\0')
    {
        if (!is_wmap(ch, NULL))
        {
            send_to_char("This only works on the world map. Go there first!\r\n", ch);
            return;
        }

        mp_x = atoi(arg2);
        mp_y = atoi(arg_x);

        if (mp_x < 0 || mp_y < 0 || mp_x > wmax_x(ch) || mp_y > wmax_y(ch))
        {
            send_to_char("Coordinates cannot exceed the map's limits.\r\n", ch);
            return;
        }
        location = victim->in_room;
    }

    else
    {
        if ((location = find_location (ch, arg2)) == NULL)
        {
            send_to_char ("No such location.\r\n", ch);
            return;
        }

        if (!is_room_owner (ch, location) && room_is_private (location)
            && get_trust (ch) < MAX_LEVEL)
        {
            send_to_char ("That room is private right now.\r\n", ch);
            return;
        }
    }

    if (victim->fighting != NULL)
        stop_fighting (victim, TRUE);
    act ("$n disappears in a mushroom cloud.", victim, NULL, NULL, TO_ROOM);
    char_from_room (victim);
    //worldmap.c
    if(mp_x >= 0 && mp_y >= 0)
    {
        set_wmap(victim,NULL,wmap_vnum_index(location->vnum));
        set_coords(victim,NULL,mp_x, mp_y);
    }
    else if(is_wmap_vnum(location->vnum))
    {
        set_wmap(victim,NULL,wmap_vnum_index(location->vnum));
        set_coords(victim,NULL,wmax_x(ch)/2,wmax_y(ch)/2);
    }
    char_to_room (victim, location);

    act ("$n arrives from a puff of smoke.", victim, NULL, NULL, TO_ROOM);
    if (ch != victim)
        act ("$n has transferred you.", ch, NULL, victim, TO_VICT);
    do_function (victim, &do_look, "auto");
    send_to_char ("Ok.\r\n", ch);
}

-act_wiz.c, do_at, make the noted changes/additions:
void do_at (CHAR_DATA * ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    ROOM_INDEX_DATA *location;
    ROOM_INDEX_DATA *original;
    OBJ_DATA *on;
    CHAR_DATA *wch;
    int orig_wmap = -1;  //worldmap.c
    int orig_x = -1;  //worldmap.c
    int orig_y = -1;  //worldmap.c
    int orig_z = 0;  //worldmap.c

    argument = one_argument (argument, arg);

    if (arg[0] == '\0' || argument[0] == '\0')
    {
        send_to_char ("At where what?\r\n", ch);
        return;
    }

    if ((location = find_location (ch, arg)) == NULL)
    {
        send_to_char ("No such location.\r\n", ch);
        return;
    }

    if (!is_room_owner (ch, location) && room_is_private (location)
        && get_trust (ch) < MAX_LEVEL)
    {
        send_to_char ("That room is private right now.\r\n", ch);
        return;
    }

    //worldmap.c
    if(is_wmap(ch,NULL))
    {
        orig_wmap = wmap_num(ch,NULL);
        orig_x = wmap_x(ch,NULL);
        orig_y = wmap_y(ch,NULL);
        orig_z = wmap_z(ch,NULL);
    }

    original = ch->in_room;
    on = ch->on;

    //worldmap.c
    if( !is_number( arg ) && ( wch = get_char_world( ch, arg ) ) != NULL
    && wch->in_room != NULL && is_wmap(wch,NULL))
    {
        char_from_room (ch);
        clone_coords(ch,NULL,wch,NULL);
        char_to_room (ch, location);
    }

    interpret (ch, argument);

    /*
     * See if 'ch' still exists before continuing!
     * Handles 'at XXXX quit' case.
     */
    for (wch = char_list; wch != NULL; wch = wch->next)
    {
        if (wch == ch)
        {
            //worldmap.c
            if(orig_x >= 0 && orig_y >= 0)
            {
                char_from_room (ch);
                set_wmap(ch,NULL,orig_wmap);
                set_coords(ch,NULL,orig_x, orig_y);
                set_z(ch,NULL,orig_z);
                char_to_room (ch, original);
            }

            ch->on = on;
            break;
        }
    }

    return;
}

-act_wiz.c, do_goto, make the noted changes/additions:
void do_goto(CHAR_DATA *ch, char *argument)
{
    ROOM_INDEX_DATA *location = NULL;
    CHAR_DATA *rch;
    int count = 0;
    int mp_x = -1, mp_y = -1;     //worldmap.c
    char arg[MAX_INPUT_LENGTH];
    char arg_x[MAX_INPUT_LENGTH];
    char arg_y[MAX_INPUT_LENGTH];

    argument = one_argument(argument, arg);
    argument = one_argument(argument, arg_x);
    argument = one_argument(argument, arg_y);

    if (arg[0] == '\0')
    {
        send_to_char("Goto where?\r\n", ch);
        return;
    }

    //worldmap.c
    if (!str_prefix(arg, "coordinates"))
    {
        if (!is_wmap(ch, NULL))
        {
            send_to_char("This only works on the world map. Go there first!\r\n", ch);
            return;
        }

        if (!is_number(arg_x) || !is_number(arg_y))
        {
            send_to_char("Syntax: goto coordinates <#> <#>\r\n"
                         "        goto <#> <#>\r\n", ch);
            return;
        }

        mp_x = atoi(arg_x);
        mp_y = atoi(arg_y);

        if (mp_x < 0 || mp_y < 0 || mp_x > wmax_x(ch) || mp_y > wmax_y(ch))
        {
            send_to_char("Coordinates cannot exceed the map's limits.\r\n", ch);
            return;
        }

        set_coords(ch, NULL, mp_x, mp_y);
    }
    else if (is_number(arg) && is_number(arg_x) && arg_y[0] == '\0')
    {
        if (!is_wmap(ch, NULL))
        {
            send_to_char("This only works on the world map. Go there first!\r\n", ch);
            return;
        }

        mp_x = atoi(arg);
        mp_y = atoi(arg_x);

        if (mp_x < 0 || mp_y < 0 || mp_x > wmax_x(ch) || mp_y > wmax_y(ch))
        {
            send_to_char("Coordinates cannot exceed the map's limits.\r\n", ch);
            return;
        }

        set_coords(ch, NULL, mp_x, mp_y);
    }
    else
    {
        if ((location = find_location(ch, arg)) == NULL)
        {
            send_to_char("No such location.\r\n", ch);
            return;
        }

        count = 0;
        for (rch = location->people; rch != NULL; rch = rch->next_in_room)
            count++;

        if (!is_room_owner(ch, location) && room_is_private(location)
            && (count > 1 || get_trust(ch) < MAX_LEVEL))
        {
            send_to_char("That room is private right now.\r\n", ch);
            return;
        }
    }

    if (ch->fighting != NULL)
        stop_fighting(ch, TRUE);

    for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
    {
        if(!same_room(ch,rch,NULL)) continue; //worldmap.c
        if (get_trust(rch) >= ch->invis_level)
        {
            if (ch->pcdata != NULL && ch->pcdata->bamfout[0] != '\0')
                act("$t", ch, ch->pcdata->bamfout, rch, TO_VICT);
            else
                act("$n leaves in a swirling mist.", ch, NULL, rch, TO_VICT);
        }
    }

    //already on map, just set coords
    if (location == NULL)
        set_coords(ch, NULL, mp_x, mp_y);
    else
    {
        #if defined (WMAP_IN_USE)
        //worldmap.c
        if( !is_number( arg ) && ( rch = get_char_world( ch, arg ) ) != NULL
        && rch->in_room != NULL && is_wmap(rch,NULL))             //coords to match victim
        {
            char_from_room (ch);
            clone_coords(ch,NULL,rch,NULL);
            char_to_room (ch, location);
        }
        else if(is_wmap_vnum(location->vnum))            //default coords for desired map
        {
            char_from_room (ch);
            set_wmap(ch,NULL,wmap_vnum_index(location->vnum));
            set_coords(ch,NULL,wmax_x(ch)/2,wmax_y(ch)/2);
            char_to_room (ch, location);
        }
        else
        {
            char_from_room (ch);
            char_to_room (ch, location);
        }
        #else
        char_from_room (ch);
        char_to_room (ch, location);
        #endif
    }

    for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
    {
        if (!same_room(ch, rch, NULL)) continue; //worldmap.c
        if (get_trust(rch) >= ch->invis_level)
        {
            if (ch->pcdata != NULL && ch->pcdata->bamfin[0] != '\0')
                act("$t", ch, ch->pcdata->bamfin, rch, TO_VICT);
            else
                act("$n appears in a swirling mist.", ch, NULL, rch, TO_VICT);
        }
    }

    do_function(ch, &do_look, "auto");
}

-act_wiz.c, in void do_ostat(), change the block of code to:
    //worldmap.c
    sprintf (buf,
             "In room: %d  In object: %s  Carried by: %s  Wear_loc: %d\r\n"
             "Map: %s/%d (%d:%d %d)  Map Reset: (%d %d:%d:%d)\r\n",
             obj->in_room == NULL ? 0 : obj->in_room->vnum,
             obj->in_obj == NULL ? "(none)" : obj->in_obj->short_descr,
             obj->carried_by == NULL ? "(none)" :
             can_see (ch, obj->carried_by) ? obj->carried_by->name
             : "someone", obj->wear_loc,
             //worldmap.c
             obj->in_room == NULL ? "NULL" : wmap_name(NULL,obj),
             obj->in_room == NULL ? -1 : wmap_num(NULL,obj),
             obj->in_room == NULL ? -1 : wmap_x(NULL,obj),
             obj->in_room == NULL ? -1 : wmap_y(NULL,obj),
             obj->in_room == NULL ? -1 : wmap_z(NULL,obj),
                 
             obj->in_room == NULL ? -1 : obj->reset_wmap[0],
             obj->in_room == NULL ? -1 : obj->reset_wmap[1],
             obj->in_room == NULL ? -1 : obj->reset_wmap[2],
             obj->in_room == NULL ? -1 : obj->reset_wmap[3]);
    send_to_char (buf, ch);

-act_wiz.c, in void do_mstat(), change the block of code to:
    //worldmap.c
    sprintf (buf,
             "Vnum: %d  Format: %s  Race: %s  Group: %d  Sex: %s  Room: %d\r\n"
             "Map: %s/%d (%d:%d %d)  Map Reset: (%d %d:%d:%d)\r\n",
             IS_NPC (victim) ? victim->pIndexData->vnum : 0,
             IS_NPC (victim) ? victim->
             pIndexData->new_format ? "new" : "old" : "pc",
             race_table[victim->race].name,
             IS_NPC (victim) ? victim->group : 0, sex_table[victim->sex].name,
             victim->in_room == NULL ? 0 : victim->in_room->vnum,
             wmap_name(victim,NULL), wmap_num(victim,NULL), wmap_x(victim,NULL), wmap_y(victim,NULL), wmap_z(victim,NULL), //worldmap.c
             victim->reset_wmap[0],victim->reset_wmap[1],victim->reset_wmap[2],victim->reset_wmap[3]); //worldmap.c
    send_to_char (buf, ch)

-act_wiz.c, in void do_violate(), add the same_room check in both places:
    for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
    {
        if(!same_room(ch,rch,NULL)) continue; //worldmap.c
        if (get_trust (rch) >= ch->invis_level)
        {
            if (ch->pcdata != NULL && ch->pcdata->bamfout[0] != '\0')
                act ("$t", ch, ch->pcdata->bamfout, rch, TO_VICT);
            else
                act ("$n leaves in a swirling mist.", ch, NULL, rch, TO_VICT);
        }
    }

    char_from_room (ch);
    char_to_room (ch, location);


    for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
    {
        if(!same_room(ch,rch,NULL)) continue; //worldmap.c
        if (get_trust (rch) >= ch->invis_level)
        {
            if (ch->pcdata != NULL && ch->pcdata->bamfin[0] != '\0')
                act ("$t", ch, ch->pcdata->bamfin, rch, TO_VICT);
            else
                act ("$n appears in a swirling mist.", ch, NULL, rch,
                     TO_VICT);
        }
    }

-act_wiz.c, in void do_clone(), add the same_room check:
        if (obj->carried_by != NULL)
            obj_to_char (clone, ch);
        else
        {
            obj_to_room (clone, ch->in_room);
            clone_coords(NULL,clone,ch,NULL); //worldmap.c
        }
        recursive_clone (ch, obj, clone);

And at the bottom, add the clone_coords call:
        char_to_room (clone, ch->in_room);
        clone_coords(clone,NULL,ch,NULL); //worldmap.c
        act ("$n has created $N.", ch, NULL, clone, TO_ROOM);
        act ("You clone $N.", ch, NULL, clone, TO_CHAR);
        sprintf (buf, "$N clones %s.", clone->short_descr);
        wiznet (buf, ch, NULL, WIZ_LOAD, WIZ_SECURE, get_trust (ch));
        return;


-act_wiz.c, in void do_mload, add the clone_coords call after char_to_room
    clone_coords(victim,NULL,ch,NULL); //worldmap.c

-act_wiz.c, in void do_oload, add the clone_coords call after obj_to_room:
        clone_coords(NULL,obj,ch,NULL); //worldmap.c

-act_wiz.c, in void do_purge, add the same_room check in the loops:
        for (victim = ch->in_room->people; victim != NULL; victim = vnext)
        {
            vnext = victim->next_in_room;
            if(!same_room(ch,victim,NULL)) continue; //worldmap.c
            if (IS_NPC (victim) && !IS_SET (victim->act, ACT_NOPURGE)
                && victim != ch /* safety precaution */ )
                extract_char (victim, TRUE);
        }

        for (obj = ch->in_room->contents; obj != NULL; obj = obj_next)
        {
            obj_next = obj->next_content;
            if(!same_room(ch,NULL,obj)) continue; //worldmap.c
            if (!IS_OBJ_STAT (obj, ITEM_NOPURGE))
                extract_obj (obj);
        }

-act_wiz.c, in void do_restore, add the same_room check in the loop:
        for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
        {
            if(!same_room(ch,vch,NULL)) continue; //worldmap.c

-act_wiz.c, in void do_peace, add the same_room check in the loop:
    for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
    {
        if(!same_room(ch,rch,NULL)) continue; //worldmap.c


-mob_cmds.c, in void do_mpmload(), add this at the bottom above the return and after char_to_room:
    clone_coords(victim,NULL,ch,NULL); //worldmap.c

-mob_cmds.c, in void do_mpoload(), add this at the bottom above the return and directly after obj_to_room:
        clone_coords(NULL,obj,ch,NULL); //worldmap.c

-mob_cmds.c, in void do_mppurge(), add the same_room checks in the loops:
        for (victim = ch->in_room->people; victim != NULL; victim = vnext)
        {
            vnext = victim->next_in_room;
            if(!same_room(ch,victim,NULL)) continue; //worldmap.c
            if (IS_NPC (victim) && victim != ch
                && !IS_SET (victim->act, ACT_NOPURGE))
                extract_char (victim, TRUE);
        }

        for (obj = ch->in_room->contents; obj != NULL; obj = obj_next)
        {
            obj_next = obj->next_content;
            if(!same_room(ch,NULL,obj)) continue; //worldmap.c
            if (!IS_SET (obj->extra_flags, ITEM_NOPURGE))
                extract_obj (obj);
        }

-mob_cmds.c, in void do_mpgoto(), add the needed code, or replace the entire function:
void do_mpgoto (CHAR_DATA * ch, char *argument)
{
    ROOM_INDEX_DATA *location = NULL;  //worldmap.c -- add = NULL
    //worldmap.c
    CHAR_DATA *rch;
    int mp_x = -1, mp_y = -1;
    char arg[MAX_INPUT_LENGTH];
    char arg_x[MAX_INPUT_LENGTH];
    char arg_y[MAX_INPUT_LENGTH];
    argument = one_argument (argument, arg);
    argument = one_argument (argument, arg_x);
    argument = one_argument (argument, arg_y);


    if (arg[0] == '\0')
    {
        bug ("Mpgoto - No argument from vnum %d.",
             IS_NPC (ch) ? ch->pIndexData->vnum : 0);
        return;
    }

    //worldmap.c
    if(!str_prefix(arg,"coordinates"))
    {
        if(!is_wmap(ch,NULL))
        {
            bug ("Mpgoto - only works on the world map from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }

        if(!is_number(arg_x) || !is_number(arg_y))
        {
            bug ("Mpgoto - bad x/y from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }
        mp_x = atoi(arg_x);
        mp_y = atoi(arg_y);

        if(mp_x < 0 || mp_y < 0 || mp_x > wmax_x(ch) || mp_y > wmax_y(ch))
        {
            bug ("Mpgoto - Coordinates cannot exceed map's limits from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }
    }
    else if (is_number(arg) && is_number(arg_x) && arg_y[0] == '\0')
    {
        if (!is_wmap(ch, NULL))
        {
            bug ("Mpgoto - only works on the world map from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }

        mp_x = atoi(arg);
        mp_y = atoi(arg_x);

        if (mp_x < 0 || mp_y < 0 || mp_x > wmax_x(ch) || mp_y > wmax_y(ch))
        {
            bug ("Mpgoto - Coordinates cannot exceed map's limits from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }
    }
    else
    {
        if ((location = find_location (ch, arg)) == NULL)
        {
            bug ("Mpgoto - No such location from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }
    }

    if (ch->fighting != NULL)
        stop_fighting (ch, TRUE);

    if(location == NULL)
        set_coords(ch,NULL,mp_x, mp_y);
    else
    {
        char_from_room (ch);
        char_to_room (ch, location);

        //worldmap.c
        if( !is_number( arg ) && ( rch = get_char_world( ch, arg ) ) != NULL
        && rch->in_room != NULL && is_wmap(rch,NULL))
            clone_coords(ch,NULL,rch,NULL); //worldmap.c
        else if(is_wmap_vnum(location->vnum))
        {
            set_wmap(ch,NULL,wmap_vnum_index(location->vnum));
            set_coords(ch,NULL,wmax_x(ch)/2,wmax_y(ch)/2);
        }
    }
    return;
}

-mob_cmds.c, in void do_mpat(), add the needed code or replace the entire function:
void do_mpat (CHAR_DATA * ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    ROOM_INDEX_DATA *location;
    ROOM_INDEX_DATA *original;
    CHAR_DATA *wch;
    OBJ_DATA *on;
    int orig_wmap = -1;  //worldmap.c
    int orig_x = -1;  //worldmap.c
    int orig_y = -1;  //worldmap.c
    int orig_z = 0;  //worldmap.c

    argument = one_argument (argument, arg);

    if (arg[0] == '\0' || argument[0] == '\0')
    {
        bug ("Mpat - Bad argument from vnum %d.",
             IS_NPC (ch) ? ch->pIndexData->vnum : 0);
        return;
    }

    if ((location = find_location (ch, arg)) == NULL)
    {
        bug ("Mpat - No such location from vnum %d.",
             IS_NPC (ch) ? ch->pIndexData->vnum : 0);
        return;
    }

    //worldmap.c
    if(is_wmap(ch,NULL))
    {
        orig_wmap = wmap_num(ch,NULL);
        orig_x = wmap_x(ch,NULL);
        orig_y = wmap_y(ch,NULL);
        orig_z = wmap_z(ch,NULL);
    }

    original = ch->in_room;
    on = ch->on;
    char_from_room (ch);
    char_to_room (ch, location);

    //worldmap.c
    if( !is_number( arg ) && ( wch = get_char_world( ch, arg ) ) != NULL
    && wch->in_room != NULL && is_wmap(wch,NULL))
        clone_coords(ch,NULL,wch,NULL);

    interpret (ch, argument);

    /*
     * See if 'ch' still exists before continuing!
     * Handles 'at XXXX quit' case.
     */
    for (wch = char_list; wch != NULL; wch = wch->next)
    {
        if (wch == ch)
        {
            char_from_room (ch);
            char_to_room (ch, original);

            //worldmap.c
            if(orig_x >= 0 && orig_y >= 0)
            {
                set_wmap(ch,NULL,orig_wmap);
                set_coords(ch,NULL,orig_x, orig_y);
                set_z(ch,NULL,orig_z);
            }

            ch->on = on;
            break;
        }
    }

    return;
}

-mob_cmds.c, in void do_mptransfer(), add the needed code or replace the entire function:
void do_mptransfer (CHAR_DATA * ch, char *argument)
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];
    char arg_x[MAX_INPUT_LENGTH];  //worldmap.c
    char arg_y[MAX_INPUT_LENGTH];  //worldmap.c
    int mp_x = -1;  //worldmap.c
    int mp_y = -1;  //worldmap.c
    ROOM_INDEX_DATA *location = NULL;  //worldmap.c -- add = NULL
    CHAR_DATA *victim;

    argument = one_argument (argument, arg1);
    argument = one_argument (argument, arg2);
    argument = one_argument (argument, arg_x); //worldmap.c
    argument = one_argument (argument, arg_y); //worldmap.c

    if (arg1[0] == '\0')
    {
        bug ("Mptransfer - Bad syntax from vnum %d.",
             IS_NPC (ch) ? ch->pIndexData->vnum : 0);
        return;
    }

    if (!str_cmp (arg1, "all"))
    {
        CHAR_DATA *victim_next;

        for (victim = ch->in_room->people; victim != NULL;
             victim = victim_next)
        {
            victim_next = victim->next_in_room;
            if(!same_room(ch,victim,NULL)) continue; //worldmap.c
            if (!IS_NPC (victim))
            {
                sprintf (buf, "%s %s", victim->name, arg2);
                do_mptransfer (ch, buf);
            }
        }
        return;
    }

    //worldmap.c -- move the victim checks from below to up here
    if ((victim = get_char_world (ch, arg1)) == NULL)
        return;
    if (victim->in_room == NULL)
        return;

    /*
     * Thanks to Grodyn for the optional location parameter.
     */
    if (arg2[0] == '\0')
    {
        location = ch->in_room;
    }
    else if(!str_prefix(arg2,"coordinates")) //worldmap.c
    {
        if(!is_wmap(victim,NULL))
        {
            bug ("Mptransfer - only works on the world map from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }

        if(!is_number(arg_x) || !is_number(arg_y))
        {
            bug ("Mptransfer - bad x/y from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }
        mp_x = atoi(arg_x);
        mp_y = atoi(arg_y);

        if(mp_x < 0 || mp_y < 0 || mp_x > wmax_x(ch) || mp_y > wmax_y(ch))
        {
            bug ("Mptransfer - Coordinates cannot exceed map's limits from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }
        location = victim->in_room;
    }
    else if (is_number(arg2) && is_number(arg_x) && arg_y[0] == '\0')
    {
        if (!is_wmap(ch, NULL))
        {
            bug ("Mptransfer - only works on the world map from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }

        mp_x = atoi(arg2);
        mp_y = atoi(arg_x);

        if (mp_x < 0 || mp_y < 0 || mp_x > wmax_x(ch) || mp_y > wmax_y(ch))
        {
            bug ("Mptransfer - Coordinates cannot exceed map's limits from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }
        location = victim->in_room;
    }
    else
    {
        if ((location = find_location (ch, arg2)) == NULL)
        {
            bug ("Mptransfer - No such location from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }

        if (room_is_private (location))
            return;
    }

    if (victim->fighting != NULL)
        stop_fighting (victim, TRUE);
    char_from_room (victim);
    //worldmap.c
    if(mp_x >= 0 && mp_y >= 0)
    {
        set_wmap(victim,NULL,wmap_vnum_index(location->vnum));
        set_coords(victim,NULL,mp_x, mp_y);
    }
    else if(is_wmap_vnum(location->vnum))
    {
        set_wmap(victim,NULL,wmap_vnum_index(location->vnum));
        set_coords(victim,NULL,wmax_x(ch)/2,wmax_y(ch)/2);
    }
    char_to_room (victim, location);

    do_look (victim, "auto");
    return;
}

-mob_cmds.c, in void do_mpotransfer(), it would be easiest to replace the entire function:
/*
 * Lets the mobile to transfer an object. The object must be in the same
 * room with the mobile.
 *
 * Syntax: mob otransfer [item name] [location|coords] <x> <y>
 */
//worldmap.c
void do_mpotransfer (CHAR_DATA * ch, char *argument)
{
    OBJ_DATA *obj;
    char arg[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char arg_x[MAX_INPUT_LENGTH];
    char arg_y[MAX_INPUT_LENGTH];
    int mp_x = -1;
    int mp_y = -1;
    ROOM_INDEX_DATA *location = NULL;

    argument = one_argument (argument, arg);
    argument = one_argument (argument, arg2);
    argument = one_argument (argument, arg_x);
    argument = one_argument (argument, arg_y);

    if (arg[0] == '\0')
    {
        bug ("MpOTransfer - Missing arg from vnum %d.",
             IS_NPC (ch) ? ch->pIndexData->vnum : 0);
        return;
    }

    if ((obj = get_obj_here (ch, arg)) == NULL)
        return;

    if (arg2[0] == '\0')
    {
        bug ("MpOTransfer - Missing arg2 from vnum %d.",
             IS_NPC (ch) ? ch->pIndexData->vnum : 0);
        return;
    }
    else if(!str_prefix(arg2,"coordinates"))
    {
        if(!is_wmap(ch,NULL))
        {
            bug ("MpOtransfer - only works on the world map from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }

        if(!is_number(arg_x) || !is_number(arg_y))
        {
            bug ("MpOtransfer - bad x/y from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }
        mp_x = atoi(arg_x);
        mp_y = atoi(arg_y);

        if(mp_x < 0 || mp_y < 0 || mp_x > wmax_x(ch) || mp_y > wmax_y(ch))
        {
            bug ("MpOtransfer - Coordinates cannot exceed map's limits from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }
        location = ch->in_room;
    }
    else if (is_number(arg2) && is_number(arg_x) && arg_y[0] == '\0')
    {
        if (!is_wmap(ch, NULL))
        {
            bug ("MpOtransfer - only works on the world map from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }

        mp_x = atoi(arg2);
        mp_y = atoi(arg_x);

        if (mp_x < 0 || mp_y < 0 || mp_x > wmax_x(ch) || mp_y > wmax_y(ch))
        {
            bug ("MpOtransfer - Coordinates cannot exceed map's limits from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }
        location = ch->in_room;
    }
    else
    {
        if ((location = find_location (ch, arg2)) == NULL)
        {
            bug ("MpOTransfer - No such location from vnum %d.",
                 IS_NPC (ch) ? ch->pIndexData->vnum : 0);
            return;
        }
    }

    if (obj->carried_by == NULL)
        obj_from_room (obj);
    else
    {
        if (obj->wear_loc != WEAR_NONE)
            unequip_char (ch, obj);
        obj_from_char (obj);
    }
    obj_to_room (obj, location);

    //worldmap.c
    if(mp_x >= 0 && mp_y >= 0)
    {
        set_wmap(NULL,obj,wmap_vnum_index(location->vnum));
        set_coords(NULL,obj,mp_x, mp_y);
    }
    else if(is_wmap_vnum(location->vnum))
    {
        set_wmap(NULL,obj,wmap_vnum_index(location->vnum));
        set_coords(NULL,obj,wmax_x(ch)/2,wmax_y(ch)/2);
    }
}

-mob_cmds.c, in void do_mpgtransfer(), add the same_room check in the loop:
    for (victim = ch->in_room->people; victim; victim = victim_next)
    {
        victim_next = victim->next_in_room;
        if(!same_room(ch,victim,NULL)) continue; //worldmap.c

-mob_cmds.c, in void do_mpgforce(), add the same_room check in the loop:
    for (vch = victim->in_room->people; vch != NULL; vch = vch_next)
    {
        vch_next = vch->next_in_room;
        if(!same_room(victim,vch,NULL)) continue; //worldmap.c

-mob_cmds.c, in void do_mpdamage, add the same_room check in the loop:
    if (fAll)
    {
        for (victim = ch->in_room->people; victim; victim = victim_next)
        {
            victim_next = victim->next_in_room;
            if(!same_room(ch,victim,NULL)) continue; //worldmap.c


Step 9: Updating effects, char/obj to/from rooms, list updates, effects.c, handler.c
-------
The main thing with effects is that we are updating those to have CHAR_DATA so that we can apply the
same_room check.  This part is very repetitive as most of these do nearly the exact same thing.  I will
detail updating acid, and repeat the process for the others.

-effects.c, update so that CHAR_DATA is included:
void acid_effect (CHAR_DATA * ch, void *vo, int level, int dam, int target) //worldmap.c

Modify the room->contents loop to include the same_room check, and the new CHAR_DATA in the call to
acid_effect:
        for (obj = room->contents; obj != NULL; obj = obj_next)
        {
            obj_next = obj->next_content;
            if(!same_room(ch,NULL,obj)) continue; //worldmap.c
            acid_effect (ch, obj, level, dam, TARGET_OBJ); //worldmap.c
        }

Update the call to acid_effect here as well:
        /* let's toast some gear */
        for (obj = victim->carrying; obj != NULL; obj = obj_next)
        {
            obj_next = obj->next_content;
            acid_effect (ch, obj, level, dam, TARGET_OBJ); //worldmap.c
        }

In the check for obj->contains, where we are dumping contents, update accordingly:
            for (t_obj = obj->contains; t_obj != NULL; t_obj = n_obj)
            {
                n_obj = t_obj->next_content;
                obj_from_obj (t_obj);
                if (obj->in_room != NULL)
                {
                    obj_to_room (t_obj, obj->in_room);
                    clone_coords(NULL,t_obj,NULL,obj); //worldmap.c
                }
                else if (obj->carried_by != NULL)
                {
                    obj_to_room (t_obj, obj->carried_by->in_room);
                    clone_coords(NULL,t_obj,obj->carried_by,NULL); //worldmap.c
                }
                else
                {
                    extract_obj (t_obj);
                    continue;
                }

                acid_effect (ch, t_obj, level / 2, dam / 2, TARGET_OBJ); //worldmap.c
            }


-handler.c, add the worldmap.h include:
#include "olc.h" //worldmap.c

-handler.c, in void affect_modify(), where the echo for dropping an obj and after obj_to_room, add:
            clone_coords(NULL,wield,ch,NULL); //worldmap.c

-handler.c, in void char_from_room(), add this near the bottom above ch->in_room = NULL:
    //worldmap.c
    if(wmap_x(ch,NULL) >= 0 || wmap_y(ch,NULL) >= 0)
    {
        set_wmap(ch,NULL,-1);
        set_coords(ch,NULL,-1,-1);
        set_z(ch,NULL,0);
    }

-handler.c, in void char_to_room(), in the !IS_NPC(ch) check, add after this: ++ch->in_room->area->nplayer;
            (you'll also want to updte the L6 to whatever level you set do_wedit in interp.c)
        //worldmap.c
        if(ch->desc && ch->desc->editor == ED_WMAP && !is_wmap_vnum(pRoomIndex->vnum))
        {
            if(IS_BUILDER (ch, ch->in_room->area))
                do_function(ch, &do_redit, "");
            else
                edit_done (ch);
        }

        if (ch->desc && ch->desc->editor == ED_ROOM && is_wmap_vnum(pRoomIndex->vnum))
        {
            if(IS_BUILDER (ch, ch->in_room->area) && get_trust(ch) >= L6)
                do_function(ch, &do_wedit, "");
            else
                edit_done (ch);
        }

further down in the same function and in the check for plague, add the same_room check in the loop:
        for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room)
        {
            if(!same_room(ch,vch,NULL)) continue; //worldmap.c

-handler.c, in void equip_char(), add at the bottom after obj_to_room:
        clone_coords(NULL,obj,ch,NULL); //worldmap.c

-handler.c, in void obj_from_room(), above "obj->in_room = NULL;" add:
    //worldmap.c
    if(wmap_x(NULL,obj) >= 0 || wmap_y(NULL,obj) >= 0)
    {
        set_wmap(NULL,obj,-1);
        set_coords(NULL,obj,-1,-1);
        set_z(NULL,obj,0);
    }

-handler.c, in CHAR_DATA *get_char_room(), add the same_room check to the loop:
    for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
    {
        if(!same_room(ch,rch,NULL)) continue; //worldmap.c

-handler.c, in OBJ_DATA *get_obj_list(), add the same_room check to the loop:
    for (obj = list; obj != NULL; obj = obj->next_content)
    {
        if (can_see_obj (ch, obj) && is_name (arg, obj->name) && same_room(ch,NULL,obj)) //worldmap.c
        {

-handler.c, in OBJ_DATA *get_obj_here(), add this under obj = get_obj_list:
    if(obj != NULL && !same_room(ch,NULL,obj))  //worldmap.c
        return NULL;

-handler.c, in bool room_is_dark(), add this at the top of the check:
    if (is_wmap_vnum(pRoomIndex->vnum)) //worldmap.c
        return FALSE;
And add between the ROOM_DARK and SUN_SET/SUN_DARK checks:
    if (!is_wmap_vnum(pRoomIndex->vnum) && (pRoomIndex->sector_type == SECT_INSIDE //worldmap.c
        || pRoomIndex->sector_type == SECT_CITY)) return FALSE;

-handler.c, paste this anywhere:
void WAIT_STATE(CHAR_DATA *ch, int npulse)
{
    if(IS_HOLYLIGHT(ch))
        return;
    ch->wait = UMAX(ch->wait, npulse);
    return;
}

void DAZE_STATE(CHAR_DATA *ch, int npulse)
{
    if(IS_HOLYLIGHT(ch))
        return;
    ch->daze = UMAX(ch->wait, npulse);
    return;
}


Step 10: The Tedious Part!  This final step, before the saving/updating/loading of area files, involves
combing through your entire source code for every instance of loops that check the ->people and ->contents
lists, and adding in the same_room check.  Additionally, nearly every char_to_room and obj_to_room call in
the code has to have coordinates set afterwards.  I will list every file and function in the QuickMUD
source where this needs to be updated, but I can't stress enough that if you have modified your code or
are installing this in a different codebase, it will be vital that you search your code for the specified
places, and some judgement and understanding of those places will be necessary.
--------
-act_comm.c     x5:
 *same_room: do_say, do_pmote, do_order, do_split (x2)

-act_obj.c     x15:
 *same_room: void get_obj, do_fill, do_drink, do_sacrifice, do_brandish, CHAR_DATA *find_keeper
 *do_get:  if (obj == NULL || !same_room(ch,NULL,obj))
  do_get: same_room check
 *do_drop: same_room check in ->contents check, in dropping coins
  do_drop: at the bottom of dropping coins
        OBJ_DATA *money = create_money(gold,silver); //worldmap.c
        obj_to_room (money, ch->in_room); //worldmap.c
        clone_coords(NULL,money,ch,NULL); //worldmap.c
        act ("$n drops some coins.", ch, NULL, NULL, TO_ROOM);
  do_drop: the case for drop all:
                obj_from_char (obj);
                obj_to_room (obj, ch->in_room);
                clone_coords(NULL,obj,ch,NULL); //worldmap.c
  *do_drink: same_room check
   do_drink: below that
        if (obj == NULL || !same_room(ch,NULL,obj)) //worldmap.c
        {
            send_to_char ("Drink what?\r\n", ch);
            return;
        }

-fight.c       x16: 
  *same_room: void check_assist (in both the rch and vch for loops), void mob_hit, void group_gain (x2)
  *clone_coords: void make_corpse (after x3 obj_to_room), void death_cry, void group_gain (obj_to_room),
    void disarm (obj_to_room)
  *void one_hit: flaming/frost/shocking:
            fire_effect (ch,(void *) victim, wield->level / 2, dam, TARGET_CHAR); //worldmap.c
            cold_effect (ch,victim, wield->level / 2, dam, TARGET_CHAR); //worldmap.c
            shock_effect (ch,victim, wield->level / 2, dam, TARGET_CHAR); //worldmap.c
  *do_dirt: change "switch (ch->in_room->sector_type)" to "switch (get_sector(ch,0,0,0)) //worldmap.c"


-healer.c       x1: same_room in do_heal

-magic.c       x41:
  *same_room: void say_spell, void do_cast, void obj_cast_spell, void spell_calm (x2),
    void spell_chain_lightning, void spell_faerie_fog, void spell_holy_word,
    void spell_mass_healing, void spell_mass_invis, void spell_ventriloquate, 
  *clone_coords: void spell_continual_light (obj_to_room), void spell_create_food (obj_to_room), 
    void spell_create_spring (obj_to_room), void spell_gate (char_to_room x2),
    void spell_heat_metal (obj_to_room x4), void spell_summon (char_to_room), 
  *the breath spells need their effects updated, along with the same_room checks:
    -void spell_acid_breath: 
    if (saves_spell (level, victim, DAM_ACID))
    {
        acid_effect (ch, victim, level / 2, dam / 4, TARGET_CHAR); //worldmap.c
        damage (ch, victim, dam / 2, sn, DAM_ACID, TRUE);
    }
    else
    {
        acid_effect (ch, victim, level, dam, TARGET_CHAR); //worldmap.c
        damage (ch, victim, dam, sn, DAM_ACID, TRUE);
    }
    
    -void spell_fire_breath: 
    fire_effect (ch, victim->in_room, level, dam / 2, TARGET_ROOM); //worldmap.c

    for (vch = victim->in_room->people; vch != NULL; vch = vch_next)
    {
        vch_next = vch->next_in_room;
        if(!same_room(ch,vch,NULL)) continue; //worldmap.c
        if (is_safe_spell (ch, vch, TRUE)
            || (IS_NPC (vch) && IS_NPC (ch)
                && (ch->fighting != vch || vch->fighting != ch)))
            continue;

        if (vch == victim)
        {                        /* full damage */
            if (saves_spell (level, vch, DAM_FIRE))
            {
                fire_effect (ch, vch, level / 2, dam / 4, TARGET_CHAR); //worldmap.c
                damage (ch, vch, dam / 2, sn, DAM_FIRE, TRUE);
            }
            else
            {
                fire_effect (ch, vch, level, dam, TARGET_CHAR); //worldmap.c
                damage (ch, vch, dam, sn, DAM_FIRE, TRUE);
            }
        }
        else
        {                        /* partial damage */

            if (saves_spell (level - 2, vch, DAM_FIRE))
            {
                fire_effect (ch, vch, level / 4, dam / 8, TARGET_CHAR); //worldmap.c
                damage (ch, vch, dam / 4, sn, DAM_FIRE, TRUE);
            }
            else
            {
                fire_effect (ch, vch, level / 2, dam / 4, TARGET_CHAR); //worldmap.c
                damage (ch, vch, dam / 2, sn, DAM_FIRE, TRUE);
            }
        }
    }
    
    -void spell_frost_breath:
    cold_effect (ch, victim->in_room, level, dam / 2, TARGET_ROOM); //worldmap.c

    for (vch = victim->in_room->people; vch != NULL; vch = vch_next)
    {
        vch_next = vch->next_in_room;
        if(!same_room(ch,vch,NULL)) continue; //worldmap.c
        if (is_safe_spell (ch, vch, TRUE)
            || (IS_NPC (vch) && IS_NPC (ch)
                && (ch->fighting != vch || vch->fighting != ch)))
            continue;

        if (vch == victim)
        {                        /* full damage */
            if (saves_spell (level, vch, DAM_COLD))
            {
                cold_effect (ch, vch, level / 2, dam / 4, TARGET_CHAR); //worldmap..c
                damage (ch, vch, dam / 2, sn, DAM_COLD, TRUE);
            }
            else
            {
                cold_effect (ch, vch, level, dam, TARGET_CHAR); //worldmap.c
                damage (ch, vch, dam, sn, DAM_COLD, TRUE);
            }
        }
        else
        {
            if (saves_spell (level - 2, vch, DAM_COLD))
            {
                cold_effect (ch, vch, level / 4, dam / 8, TARGET_CHAR); //worldmap.c
                damage (ch, vch, dam / 4, sn, DAM_COLD, TRUE);
            }
            else
            {
                cold_effect (ch, vch, level / 2, dam / 4, TARGET_CHAR); //worldmap.c
                damage (ch, vch, dam / 2, sn, DAM_COLD, TRUE);
            }
        }
    }

    -void spell_gas_breath: 
    poison_effect (ch, ch->in_room, level, dam, TARGET_ROOM); //worldmap.c

    for (vch = ch->in_room->people; vch != NULL; vch = vch_next)
    {
        vch_next = vch->next_in_room;
        if(!same_room(ch,vch,NULL)) continue; //worldmap.c
        if (is_safe_spell (ch, vch, TRUE)
            || (IS_NPC (ch) && IS_NPC (vch)
                && (ch->fighting == vch || vch->fighting == ch)))
            continue;

        if (saves_spell (level, vch, DAM_POISON))
        {
            poison_effect (ch, vch, level / 2, dam / 4, TARGET_CHAR); //worldmap.c
            damage (ch, vch, dam / 2, sn, DAM_POISON, TRUE);
        }
        else
        {
            poison_effect (ch, vch, level, dam, TARGET_CHAR); //worldmap.c
            damage (ch, vch, dam, sn, DAM_POISON, TRUE);
        }
    }

    -void spell_lightning_breath: 
    if (saves_spell (level, victim, DAM_LIGHTNING))
    {
        shock_effect (ch, victim, level / 2, dam / 4, TARGET_CHAR); //worldmap.c
        damage (ch, victim, dam / 2, sn, DAM_LIGHTNING, TRUE);
    }
    else
    {
        shock_effect (ch, victim, level, dam, TARGET_CHAR); //worldmap.c
        damage (ch, victim, dam, sn, DAM_LIGHTNING, TRUE);
    }

-magic2.c       x6: 
  *void spell_portal:
    if(is_wmap(victim,NULL)) //worldmap.c
    {
        portal->value[4] = wmap_num(victim,NULL);
        portal->value[5] = wmap_x(victim,NULL);
        portal->value[6] = wmap_y(victim,NULL);
    }

    obj_to_room (portal, ch->in_room);
    clone_coords(NULL,portal,ch,NULL); //worldmap.c

  *void spell_nexus:
    if(is_wmap(victim,NULL)) //worldmap.c
    {
        portal->value[4] = wmap_num(victim,NULL);
        portal->value[5] = wmap_x(victim,NULL);
        portal->value[6] = wmap_y(victim,NULL);
    }

    obj_to_room (portal, from_room);
    clone_coords(NULL,portal,ch,NULL); //worldmap.c

    act ("$p rises up from the ground.", ch, portal, NULL, TO_ROOM);
    act ("$p rises up before you.", ch, portal, NULL, TO_CHAR);

    /* no second portal if rooms are the same */
    if (to_room == from_room && !is_wmap_vnum(to_room->vnum))
        return;

    /* portal two */
    portal = create_object (get_obj_index (OBJ_VNUM_PORTAL), 0);
    portal->timer = 1 + level / 10;
    portal->value[3] = from_room->vnum;

    if(is_wmap(ch,NULL)) //worldmap.c
    {
        portal->value[4] = wmap_num(ch,NULL);
        portal->value[5] = wmap_x(ch,NULL);
        portal->value[6] = wmap_y(ch,NULL);
    }

    obj_to_room (portal, to_room);
    clone_coords(NULL,portal,victim,NULL); //worldmap.c

-mob_prog.c     x8: 
  *same_room: CHAR_DATA *get_random_char, int count_people_room, int get_order, bool get_mob_vnum_room,
    bool get_obj_vnum_room, bool mp_exit_trigger, void mp_greet_trigger
  *int cmd_eval: find this:
    /*
     * From now on, we need an actor, so if none was found, bail out
     */
    if (lval_char == NULL && lval_obj == NULL)
        return FALSE;

    and put this under it:
    //worldmap.c
    if( (lval_char != NULL && !same_room(mob,lval_char,NULL))
    ||  (lval_char != NULL && !same_room(mob,NULL,lval_obj)) )
        return FALSE;

-music.c        x2: 
  *void do_play:
    for (juke = ch->in_room->contents; juke != NULL; juke = juke->next_content)
    {
        if(!same_room(ch,NULL,juke)) continue; //worldmap.c
        if (juke->item_type == ITEM_JUKEBOX && can_see_obj (ch, juke))
            break;
    }

    if (argument[0] == '\0')
    {
        send_to_char ("Play what?\r\n", ch);
        return;
    }

    if (juke == NULL || !same_room(ch,NULL,juke)) //worldmap.c
    {
        send_to_char ("You see nothing to play.\r\n", ch);
        return;
    }

-nanny.c        x1: note that your game MAY have the nanny function located inside of comm.c instead of
                    being its own file.  In the section where a pet enters the game, it add the
                    clone_coords after char_to_room


-skills.c       x2: 
  *void do_gain:
    /* find a trainer */
    for (trainer = ch->in_room->people; trainer != NULL; trainer = trainer->next_in_room)
    {
        if(!same_room(ch,trainer,NULL)) continue; //worldmap.c
        if (IS_NPC (trainer) && IS_SET (trainer->act, ACT_GAIN))
            break;
    }

    if (trainer == NULL || !can_see (ch, trainer) || !same_room(ch,trainer,NULL)) //worldmap.c
    {
        send_to_char ("You can't do that here.\r\n", ch);
        return;
    }

-special.c     x25: 
  *same_room: bool spec_troll_member, bool spec_ogre_member, bool spec_patrolman, bool spec_nasty,
    bool spec_fido, bool spec_janitor, bool spec_thief

  *clone_coords: bool spec_fido (obj_to_room)

  *These require both a same_room check in their for loops, and then a same_room check outside of the
    loop where it checks for the victim being NULL.  The 'bool dragon' function is shown as an example.
    -bool dragon, bool spec_cast_adept, bool spec_cast_cleric, bool spec_cast_judge, bool spec_cast_mage,
      bool spec_cast_undead, bool spec_executioner, bool spec_guard (victim and ech checks):
    for (victim = ch->in_room->people; victim != NULL; victim = v_next)
    {
        v_next = victim->next_in_room;
        if(!same_room(ch,victim,NULL)) continue; //worldmap.c
        if (victim->fighting == ch && number_bits (3) == 0)
            break;
    }

    if (victim == NULL || !same_room(ch,victim,NULL)) //worldmap.c
        return FALSE;


-update.c       x8: 
  *same_room: void char_update, void aggr_update x2
  *clone_coords: void obj_update (obj_to_room x2)
  
  *add the worldmap.h include at the top:
#include "worldmap.h" //worldmap.c

 *void mobile_update: add the same_room check, and the wander/ACT_SENTINEL check needs updating as shown:
         /* Wander */
        if (!IS_SET (ch->act, ACT_SENTINEL)
            && number_bits (3) == 0

            //worldmap.c
            && ((is_wmap(ch,NULL) && (door = number_bits (5)) <= 9 && door != DIR_UP && door != DIR_DOWN
            && get_sector(ch,0,0,0) == get_sector(NULL,wmap_num(ch,NULL),wmap_new_x(ch,door),wmap_new_y(ch,door))
                && ((door >= DIR_NORTHEAST && can_enter(ch, NULL, TRUE, wmap_x(ch, NULL), wmap_new_y(ch,door)) && can_enter(ch, NULL, TRUE, wmap_new_x(ch,door), wmap_y(ch, NULL)))
                    || can_enter(ch, NULL, TRUE, wmap_new_x(ch,door), wmap_new_y(ch,door))))
    
            || ((door = number_bits (5)) <= 5
            && (pexit = ch->in_room->exit[door]) != NULL
            && pexit->u1.to_room != NULL
            && !IS_SET (pexit->exit_info, EX_CLOSED)
            && !IS_SET (pexit->u1.to_room->room_flags, ROOM_NO_MOB)
            && (!IS_SET (ch->act, ACT_STAY_AREA)
                || pexit->u1.to_room->area == ch->in_room->area)
            && (!IS_SET (ch->act, ACT_OUTDOORS)
                || !IS_SET (pexit->u1.to_room->room_flags, ROOM_INDOORS))
            && (!IS_SET (ch->act, ACT_INDOORS)
                || IS_SET (pexit->u1.to_room->room_flags, ROOM_INDOORS)))))


***Additional notes: there are some places where the same_room or clone_coords do not need to be added,
   which is why it was mentioned earlier some judgement calls would need to be made.  I tried to make the
   following list as exhaustive as possible, but it's possible some were missed, and as always, if your
   code has been significantly modified or you are using a different base, this will just be some examples
   of where some of this does not need to be added:

   char_to_room()/obj_to_room()
   clone_coords: redit_mreset, do_violate, copyover_recover, do_buy, do_recall (unless players are able
   to recall to the map), do_redit, reset_room, extract_char, nanny (for PCs), teleport, redit_oreset

   ->people
   same_room: do_goto (player count part), rstat, redit_show, scan_list, do_list (for pets), reset_room,
     count_users, obj_from_room, room_is_private
       -any if check that has ->people it contains calls to "act" for messaging purposes, the loops that
        contain the check if someone is on an obj, 

   ->contents
   same_room: rstat, obj_from_room, redit_show


Step 11: Saving the world!  Everything should be in now other than the loading of the new object values
which is where things can go wrong if not done in the correct order, db.c, db2.c
--------
-do a clean compile (make clean, followed by make).  If we didn't miss anything, the code should compile
  without any errors.  If there is, you'll need to fix those before proceeding.  After compiling, do a
  copyover or reboot.  The game should load without issue.
-do an "asave world" to write every area file in the game, which should update all objects in the game to
  have the value[5] and value[6] values added.
-now we will update the remaining functions in db.c and db2.c to handle loading objects and the map(s).

-db.c: add the worldmap.h include:
#include "worldmap.h" //worldmap.c

-db.c: near the top under the local booting proceedures, at the bottom add:
//worldmap.c
void load_wmap args((int map_index));
void load_wmap_resets args((int wmap_index));

-db.c: in void boot_db(), at the bottom just above return, add:
    //worldmap.c
    for (int i = 0; i < MAX_WMAP; i ++)
    {
        load_wmap(i);
        load_wmap_resets(i);
    }
    load_wmap_exits();
    load_wmap_tiles();
    process_wmap_resets();

-db.c: in OBJ_DATA *create_object(), add the new value[] valiues:
    obj->value[5] = pObjIndex->value[5]; //worldmap.c
    obj->value[6] = pObjIndex->value[6]; //worldmap.c


-db2.c: in void load_objects(), add this for every listed case in the switch for item type:
                pObjIndex->value[5] = fread_flag (fp); //worldmap.c
                pObjIndex->value[6] = fread_flag (fp); //worldmap.c

-Make sure that you have your map PNG files in place.  Do another clean compile followed by a copyover
  or reboot.  If the game loads, then everything should be in place and ready to rock.

----------------------------------------------------------------------------------------------------------

If you have opted to use the alternate commands in place of the WEdit stuff, you can find that code in
the worldmap_alt.txt file.  If you've made it this far, figuring out installation of the alternate
commands should be a breeze by comparison.

Feedback is welcome, along with bug reports or even contribution to the project.  Future versions may be
released and may contain contributions from others.

The StockMUD+ [ROM] project located at stockmud.com, port 5001 is the homebase for the project, and its
associated discord can be found at:  https://discord.gg/pBxt7F8

Congrats on the installation, and enjoy!
