/* $Id: olc_area.c,v 1.666 2004/09/20 10:50:30 shrike Exp $ */ /************************************************************************************ * Copyright 2004 Astrum Metaphora consortium * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * * ************************************************************************************/ /************************************************************************************ * ANATOLIA 2.1 is copyright 1996-1997 Serdar BULUT, Ibrahim CANPUNAR * * ANATOLIA has been brought to you by ANATOLIA consortium * * Serdar BULUT {Chronos} bulut@rorqual.cc.metu.edu.tr * * Ibrahim Canpunar {Asena} canpunar@rorqual.cc.metu.edu.tr * * Murat BICER {KIO} mbicer@rorqual.cc.metu.edu.tr * * D.Baris ACAR {Powerman} dbacar@rorqual.cc.metu.edu.tr * * By using this code, you have agreed to follow the terms of the * * ANATOLIA license, in the file Anatolia/anatolia.licence * ***********************************************************************************/ /************************************************************************************ * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ************************************************************************************/ /************************************************************************************ * ROM 2.4 is copyright 1993-1995 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@pacinfo.com) * * Gabrielle Taylor (gtaylor@pacinfo.com) * * Brian Moore (rom@rom.efn.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * *************************************************************************************/ /************************************************************************************ * Copyright (c) 1998 fjoe <fjoe@iclub.nsu.ru> * * All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * 1. Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * * SUCH DAMAGE. * ************************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include "merc.h" #include "olc.h" #include "db/db.h" #include "conquer.h" #define EDIT_AREA(ch, area) (area = (AREA_DATA*) ch->desc->pEdit) DECLARE_OLC_FUN(areaed_create ); DECLARE_OLC_FUN(areaed_edit ); DECLARE_OLC_FUN(areaed_touch ); DECLARE_OLC_FUN(areaed_show ); DECLARE_OLC_FUN(areaed_list ); DECLARE_OLC_FUN(areaed_name ); DECLARE_OLC_FUN(areaed_mlname ); DECLARE_OLC_FUN(areaed_file ); DECLARE_OLC_FUN(areaed_flags ); DECLARE_OLC_FUN(areaed_age ); DECLARE_OLC_FUN(areaed_reset ); DECLARE_OLC_FUN(areaed_security ); DECLARE_OLC_FUN(areaed_builders ); DECLARE_OLC_FUN(areaed_resetmsg ); DECLARE_OLC_FUN(areaed_minvnum ); DECLARE_OLC_FUN(areaed_maxvnum ); DECLARE_OLC_FUN(areaed_move ); DECLARE_OLC_FUN(areaed_credits ); DECLARE_OLC_FUN(areaed_minlevel ); DECLARE_OLC_FUN(areaed_maxlevel ); DECLARE_OLC_FUN(areaed_clan ); DECLARE_OLC_FUN(areaed_climat ); DECLARE_OLC_FUN(areaed_maxguards ); DECLARE_OLC_FUN(areaed_guardrooms ); DECLARE_OLC_FUN(areaed_explore_req ); DECLARE_OLC_FUN(areaed_planet ); DECLARE_OLC_FUN(areaed_timezone ); DECLARE_OLC_FUN(areaed_xcoordinat ); DECLARE_OLC_FUN(areaed_ycoordinat ); DECLARE_OLC_FUN(areaed_zcoordinat ); DECLARE_OLC_FUN(areaed_breadth ); DECLARE_OLC_FUN(areaed_longitude ); DECLARE_VALIDATE_FUN(validate_security ); DECLARE_VALIDATE_FUN(validate_minvnum ); DECLARE_VALIDATE_FUN(validate_maxvnum ); DECLARE_VALIDATE_FUN(validate_move ); DECLARE_VALIDATE_FUN(validate_maxguards ); olc_cmd_t olc_cmds_area[] = { { "create", areaed_create, 5 }, { "edit", areaed_edit, 5 }, { "touch", areaed_touch, 5 }, { "show", areaed_show, 5 }, { "list", areaed_list, 5 }, { "name", areaed_name, 5 }, { "mlname", areaed_mlname, 5 }, { "filename", areaed_file, 5, validate_filename }, { "area", areaed_flags, 5, area_flags }, { "age", areaed_age, 5 }, { "reset", areaed_reset, 0 }, { "security", areaed_security, 5, validate_security }, { "builders", areaed_builders, 5 }, { "resetmsg", areaed_resetmsg, 0 }, { "minvnum", areaed_minvnum, 0, validate_minvnum }, { "maxvnum", areaed_maxvnum, 0, validate_maxvnum }, { "move", areaed_move, 5, validate_move }, { "credits", areaed_credits, 5 }, { "minlevel", areaed_minlevel, 0 }, { "maxlevel", areaed_maxlevel, 0 }, { "clan", areaed_clan, 5 }, { "commands", show_commands, 0 }, { "version", show_version, 0 }, { "climat", areaed_climat, 0, climat_flags }, { "planet", areaed_planet, 0, planet_flags }, { "maxguards", areaed_maxguards, 0, validate_maxguards }, { "guardrooms", areaed_guardrooms, 0 }, { "explorereq", areaed_explore_req, 0 }, { "longitude", areaed_longitude, 0 }, { "breadth", areaed_breadth, 0 }, { "timezone", areaed_timezone, 0 }, { "xcoordinate", areaed_xcoordinat, 0 }, { "ycoordinate", areaed_ycoordinat, 0 }, { "zcoordinate", areaed_zcoordinat, 0 }, { NULL } }; AREA_DATA *check_range(AREA_DATA *pArea, int ilower, int iupper); /* * Area Editor Functions. */ OLC_FUN(areaed_create) { AREA_DATA *pArea; if (ch->pcdata->security < SECURITY_AREA_CREATE) { char_puts("AreaEd: Insufficient security.\n", ch); return FALSE; } pArea = new_area(); area_last->next = pArea; area_last = pArea; /* Thanks, Walker. */ ch->desc->pEdit = (void*) pArea; OLCED(ch) = olced_lookup(ED_AREA); touch_area(pArea); char_puts("AreaEd: Area created.\n", ch); return FALSE; } OLC_FUN(areaed_edit) { AREA_DATA *pArea; char arg[MAX_STRING_LENGTH]; one_argument(argument, arg, sizeof(arg)); if (arg[0] == '\0') pArea = ch->in_room->area; else if (!is_number(arg) || (pArea = area_lookup(atoi(arg))) == NULL) { char_puts("AreaEd: That area vnum does not exist.\n", ch); return FALSE; } if (!IS_BUILDER(ch, pArea)) { char_puts("AreaEd: Insufficient security.\n", ch); return FALSE; } ch->desc->pEdit = (void *) pArea; OLCED(ch) = olced_lookup(ED_AREA); return FALSE; } OLC_FUN(areaed_touch) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return touch_area(pArea); } OLC_FUN(areaed_show) { AREA_DATA *pArea; char arg[MAX_STRING_LENGTH]; int i; BUFFER *output; one_argument(argument, arg, sizeof(arg)); if (arg[0] == '\0') { if (IS_EDIT(ch, ED_AREA)) EDIT_AREA(ch, pArea); else pArea = ch->in_room->area; } else if (!is_number(arg) || (pArea = area_lookup(atoi(arg))) == NULL) { char_puts("AreaEd: That area vnum does not exist.\n", ch); return FALSE; } if (!IS_BUILDER(ch, pArea)) { char_puts("AreaEd: Insufficient security.\n", ch); return FALSE; } output = buf_new(ch->lang); buf_printf(output, "Name: [%5d] %s\n", pArea->vnum, pArea->name); mlstr_dump(output, "ML name: ", pArea->mlname); buf_printf(output, "File: %s\n", pArea->file_name); buf_printf(output, "Version: [%.2lf]\n", pArea->version); buf_printf(output, "Vnums: [%d-%d]\n", pArea->min_vnum, pArea->max_vnum); buf_printf(output, "Levels: [%d-%d]\n", pArea->min_level, pArea->max_level); if (pArea->clan) buf_printf(output, "Clan: [%s]\n", clan_name(pArea->clan)); buf_printf(output, "Age: [%d]\n", pArea->age); buf_printf(output, "Players: [%d]\n", pArea->nplayer); buf_printf(output, "Security: [%d]\n", pArea->security); if (!IS_NULLSTR(pArea->builders)) buf_printf(output, "Builders: [%s]\n", pArea->builders); buf_printf(output, "Credits: [%s]\n", pArea->credits); buf_printf(output, "Flags: [%s]\n", flag_string(area_flags, pArea->flags)); buf_printf(output, "Climat: [%s]\n\r", flag_string(climat_flags, pArea->climat_type)); buf_printf(output, "Planet: [%s]\n\r", flag_string(planet_flags, pArea->planet)); buf_printf(output, "Longitude: [%-2f]\n\r", pArea->longitude); buf_printf(output, "Breadth: [%-2f]\n\r", pArea->breadth); buf_printf(output, "Time Zone: [%d]\n\r", pArea->timezone); buf_printf(output, "X Coordinate: [%d]\n\r", pArea->x_coord); buf_printf(output, "Y Coordinate: [%d]\n\r", pArea->y_coord); buf_printf(output, "Z Coordinate: [%d]\n\r", pArea->z_coord); buf_printf(output, "Sun rise/set: [%-2d] [%-2d]\n\r", pArea->sunrise, pArea->sunset); buf_printf(output, "MaxGuards: [%d]\n", pArea->max_guard_count); buf_printf(output, "GuardRooms: ["); for (i = 0; i < MAX_GUARD_COUNT; ++i) if (pArea->guard_room_vnums[i] != 0) buf_printf(output, " %d ", pArea->guard_room_vnums[i]); buf_printf(output, "]\n"); buf_printf(output, "\n"); switch (pArea->explore_required) { case EXPLORE_NOT_REQ: buf_printf(output, "Explore before conquer: NOT REQUIRED\n"); break; case EXPLORE_GUARDROOMS_REQ: buf_printf(output, "Explore before conquer: ROOMS MUST BE EXPLORED\n"); break; case EXPLORE_ALL_AREA_REQ: buf_printf(output, "Explore before conquer: WHOLE AREA MUST BE EXPLORED\n"); break; } page_to_char(buf_string(output), ch); buf_free(output); return FALSE; } OLC_FUN(areaed_climat) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_flag64(ch, argument, cmd, &pArea->climat_type); } OLC_FUN(areaed_planet) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_flag64(ch, argument, cmd, &pArea->planet); } OLC_FUN(areaed_list) { char arg[MAX_STRING_LENGTH]; AREA_DATA *pArea; BUFFER *output = NULL; one_argument(argument, arg, sizeof(arg)); for (pArea = area_first; pArea; pArea = pArea->next) { if (arg[0] != '\0' && !strstr(strlwr(pArea->name), arg)) continue; if (!IS_BUILDER(ch, pArea)) continue; if (output == NULL) { output = buf_new(-1); buf_printf(output, "[%3s] [%-27s] (%-5s-%5s) [%-10s] %3s [%-10s]\n", "Num", "Area Name", "lvnum", "uvnum", "Filename", "Sec", "Builders"); } buf_printf(output, "[%3d] %s (%-5d-%5d) %-12.12s [%d] [%-10.10s]\n", pArea->vnum, fmt_color_str(pArea->name, 29), pArea->min_vnum, pArea->max_vnum, pArea->file_name, pArea->security, pArea->builders); } if (output != NULL) { send_to_char(buf_string(output), ch); buf_free(output); } else char_puts("No areas with that name found.\n", ch); return FALSE; } OLC_FUN(areaed_reset) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); reset_area(pArea); char_puts("Area reset.\n", ch); return FALSE; } OLC_FUN(areaed_name) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_str(ch, argument, cmd, &pArea->name); } OLC_FUN(areaed_mlname) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_mlstr(ch, argument, cmd, &pArea->mlname); } OLC_FUN(areaed_credits) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_str(ch, argument, cmd, &pArea->credits); } OLC_FUN(areaed_file) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_str(ch, argument, cmd, &pArea->file_name); } OLC_FUN(areaed_age) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_number(ch, argument, cmd, &pArea->age); } OLC_FUN(areaed_longitude) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_double(ch, argument, cmd, &pArea->longitude); } OLC_FUN(areaed_breadth) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_double(ch, argument, cmd, &pArea->breadth); } OLC_FUN(areaed_timezone) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_number(ch, argument, cmd, &pArea->timezone); } OLC_FUN(areaed_xcoordinat) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_number(ch, argument, cmd, &pArea->x_coord); } OLC_FUN(areaed_ycoordinat) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_number(ch, argument, cmd, &pArea->y_coord); } OLC_FUN(areaed_zcoordinat) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_number(ch, argument, cmd, &pArea->z_coord); } OLC_FUN(areaed_flags) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_flag64(ch, argument, cmd, &pArea->flags); } OLC_FUN(areaed_security) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_number(ch, argument, cmd, &pArea->security); } OLC_FUN(areaed_minlevel) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_number(ch, argument, cmd, &pArea->min_level); } OLC_FUN(areaed_maxlevel) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_number(ch, argument, cmd, &pArea->max_level); } OLC_FUN(areaed_resetmsg) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_mlstr(ch, argument, cmd, &pArea->resetmsg); } OLC_FUN(areaed_builders) { AREA_DATA *pArea; char name[MAX_STRING_LENGTH]; EDIT_AREA(ch, pArea); one_argument(argument, name, sizeof(name)); if (name[0] == '\0') { do_help(ch, "'OLC AREA BUILDER'"); return FALSE; } if (ch->pcdata->security < SECURITY_AREA_CREATE && is_name_raw(ch->name, pArea->builders, str_cmp)) { char_puts("AreaEd: Insufficient security.\n", ch); return FALSE; } name_toggle(ch, name, "AreaEd", &pArea->builders); return TRUE; } OLC_FUN(areaed_minvnum) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_number(ch, argument, cmd, &pArea->min_vnum); } OLC_FUN(areaed_maxvnum) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_number(ch, argument, cmd, &pArea->max_vnum); } OLC_FUN(areaed_move) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_number(ch, argument, cmd, &pArea->min_vnum); } OLC_FUN(areaed_clan) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_clan(ch, argument, cmd, &pArea->clan); } OLC_FUN(areaed_maxguards) { AREA_DATA *pArea; EDIT_AREA(ch, pArea); return olced_number(ch, argument, cmd, &pArea->max_guard_count); } OLC_FUN(areaed_guardrooms) { int val, i; char *endptr; char arg[MAX_STRING_LENGTH]; AREA_DATA *pArea; ROOM_INDEX_DATA *pRoomIndex; EDIT_AREA(ch, pArea); one_argument(argument, arg, sizeof(arg)); val = strtol(arg, &endptr, 0); if (*arg == '\0' || *endptr != '\0') { char_printf(ch, "Syntax: guardroom number\n"); return FALSE; } // validator has been placed here, because there is no number_toggle function if ((val < pArea->min_vnum) || (val > pArea->max_vnum)) { char_printf(ch, "AEdit: vnum must be between %d and %d for this area.\n", pArea->min_vnum, pArea->max_vnum); return FALSE; } if (!(pRoomIndex = get_room_index(val))) { char_printf(ch, "AEdit: guardroom vnum %d does not exist.\n", val); return FALSE; } // trying to find vnum. if it exists we have to delete it from array for (i=0; i < pArea->max_guard_count; ++i) { if (pArea->guard_room_vnums[i] == val) { pArea->guard_room_vnums[i] = 0; char_printf(ch, "%d: room vnum deleted.\n", val); return TRUE; } } //trying to find empty space for vnum for (i=0; i < pArea->max_guard_count; ++i) { if (pArea->guard_room_vnums[i] == 0) { pArea->guard_room_vnums[i] = val; char_printf(ch, "%d: room vnum added.\n", val); return TRUE; } } // vnum does not exist in list and there are no space for adding char_printf(ch, "AEdit: room vnums limit reached. Room %d was not added.\n", val); return FALSE; } OLC_FUN(areaed_explore_req) { char arg[MAX_STRING_LENGTH]; AREA_DATA *pArea; EDIT_AREA(ch, pArea); one_argument(argument, arg, sizeof(arg)); //possible values: no/rooms/all if (!str_prefix(arg, "no")) { pArea->explore_required = EXPLORE_NOT_REQ; char_act("Now char must not explore this area before conquer it.", ch); return TRUE; } if (!str_prefix(arg, "rooms")) { pArea->explore_required = EXPLORE_GUARDROOMS_REQ; char_act("Now char must explore guardrooms in this area before conquer it.", ch); return TRUE; } if (!str_prefix(arg, "all")) { pArea->explore_required = EXPLORE_ALL_AREA_REQ; char_act("Now char must completely explore this area before conquer it.", ch); return TRUE; } // incorrect value char_printf(ch, "AEdit: %s - incorrect value. Possible values: no/rooms/all.\n", arg); return FALSE; } /* Validators */ VALIDATE_FUN(validate_security) { int sec = *(int*) arg; if (sec > ch->pcdata->security || sec < 0) { if (ch->pcdata->security != 0) char_printf(ch, "AreaEd: Valid security range is 0..%d.\n", ch->pcdata->security); else char_puts("AreaEd: Valid security is 0 only.\n", ch); return FALSE; } return TRUE; } VALIDATE_FUN(validate_minvnum) { int min_vnum = *(int*) arg; AREA_DATA *pArea; EDIT_AREA(ch, pArea); if (min_vnum && pArea->max_vnum) { if (min_vnum > pArea->max_vnum) { char_puts("AreaEd: Min vnum must be less than max vnum.\n", ch); return FALSE; } if (check_range(pArea, min_vnum, pArea->max_vnum)) { char_puts("AreaEd: Range must include only this area.\n", ch); return FALSE; } } return TRUE; } VALIDATE_FUN(validate_maxvnum) { int max_vnum = *(int*) arg; AREA_DATA *pArea; EDIT_AREA(ch, pArea); if (pArea->min_vnum && max_vnum) { if (max_vnum < pArea->min_vnum) { char_puts("AreaEd: Max vnum must be greater than min vnum.\n", ch); return FALSE; } if (check_range(pArea, pArea->min_vnum, max_vnum)) { char_puts("AreaEd: Range must include only this area.\n", ch); return FALSE; } } return TRUE; } VALIDATE_FUN(validate_maxguards) { int value = *(int*) arg; if (value <0 || value > MAX_GUARD_COUNT) { char_printf(ch, "AEdit: Guard count for area must be between 0 and %d.\n", MAX_GUARD_COUNT); return FALSE; } return TRUE; } #define IN_RANGE(i, l, u) ((l) <= (i) && (i) <= (u)) #define MOVE(i) if (IN_RANGE(i, pArea->min_vnum, pArea->max_vnum)) { \ i += delta; \ touched = TRUE; \ } static void move_mob(MOB_INDEX_DATA *mob, AREA_DATA *pArea, int delta); static void move_obj(OBJ_INDEX_DATA *obj, AREA_DATA *pArea, int delta); static void move_room(ROOM_INDEX_DATA *room, AREA_DATA *pArea, int delta); VALIDATE_FUN(validate_move) { int i; int new_min = *(int*) arg; int delta; bool touched; AREA_DATA *pArea; MPCODE *mpc; clan_t *clan; religion_t *religion; hometown_t *hometown; EDIT_AREA(ch, pArea); if (ch->pcdata->security < SECURITY_AREA_CREATE) { char_puts("AreaEd: Insufficient security.\n", ch); return FALSE; } if (!pArea->min_vnum || !pArea->max_vnum) { char_puts("AreaEd: Both min_vnum and max_vnum must be set " "in order to perform area vnum move.\n", ch); return FALSE; } /* check new region */ delta = new_min - pArea->min_vnum; if (check_range(pArea, new_min, pArea->max_vnum+delta)) { char_puts("AreaEd: New vnum range overlaps other areas.\n", ch); return FALSE; } /* everything is ok -- change vnums of all rooms, objs, mobs in area */ /* fix hometowns */ touched = FALSE; for (i = 0; i < hometowns.nused; i++) { int j; bool touched2 = touched; touched = FALSE; hometown = HOMETOWN(i); for (j = 0; j < MAX_ANUM; j++) { if (IN_RANGE(hometown->recall[j]->vnum, pArea->min_vnum, pArea->max_vnum)) touched = TRUE; if (IN_RANGE(hometown->map[j]->vnum, pArea->min_vnum, pArea->max_vnum)) touched = TRUE; if (IN_RANGE(hometown->altar[j].room->vnum, pArea->min_vnum, pArea->max_vnum)) touched = TRUE; if (IN_RANGE(hometown->altar[j].pit->vnum, pArea->min_vnum, pArea->max_vnum)) touched = TRUE; } if (touched) touch_hometown(hometown); else touched = touched2; } if (touched) { char_puts("AreaEd: Changed hometowns:\n", ch); for (i = 0; i < hometowns.nused; i++) { hometown = HOMETOWN(i); if (IS_SET(hometown->flags, HOMETOWN_CHANGED)) char_printf(ch, "- %s\n", hometown->area); } } /* fix religion tattoo vnum */ touched = FALSE; for (i = 0; i < religions.nused; i++) { bool touched2 = touched; touched = FALSE; religion = RELIGION(i); MOVE(religion->tattoo_vnum); if (touched) touch_religion(religion); else touched = touched2; } if (touched) { char_puts("AreaEd: Changed religions:\n", ch); for (i = 0; i < religions.nused; i++) { religion = RELIGION(i); if (IS_SET(religion->flags, RELIGION_CHANGED)) char_printf(ch, "- %s\n", religion->name); } } /* fix clan recall, item and altar vnums */ touched = FALSE; for (i = 0; i < clans.nused; i++) { bool touched2 = touched; touched = FALSE; clan = CLAN(i); MOVE(clan->altar_vnum); MOVE(clan->recall_vnum); MOVE(clan->obj_vnum); MOVE(clan->mark_vnum); MOVE(clan->altar_trophy_vnum); MOVE(clan->item_at); if (touched) touch_clan(clan); else touched = touched2; } if (touched) { char_puts("AreaEd: Changed clans:\n", ch); for (i = 0; i < clans.nused; i++) { clan = CLAN(i); if (IS_SET(clan->flags, CLAN_CHANGED)) char_printf(ch, "- %s\n", clan->name); } } /* fix mprogs */ for (mpc = mpcode_list; mpc; mpc = mpc->next) MOVE(mpc->vnum); /* fix oprogs */ for (mpc = opcode_list; mpc; mpc = mpc->next) MOVE(mpc->vnum); /* fix rprogs */ for (mpc = rpcode_list; mpc; mpc = mpc->next) MOVE(mpc->vnum); /* fix mobs */ for (i = 0; i < MAX_KEY_HASH; i++) { MOB_INDEX_DATA *mob; for (mob = mob_index_hash[i]; mob; mob = mob->next) move_mob(mob, pArea, delta); } /* fix objs */ for (i = 0; i < MAX_KEY_HASH; i++) { OBJ_INDEX_DATA *obj; for (obj = obj_index_hash[i]; obj; obj = obj->next) move_obj(obj, pArea, delta); } /* fix rooms */ for (i = 0; i < MAX_KEY_HASH; i++) { ROOM_INDEX_DATA *room; for (room = room_index_hash[i]; room; room = room->next) move_room(room, pArea, delta); } /* rebuild mob index hash */ top_vnum_mob = 0; for (i = 0; i < MAX_KEY_HASH; i++) { MOB_INDEX_DATA *mob, *mob_next, *mob_prev = NULL; for (mob = mob_index_hash[i]; mob; mob = mob_next) { int mob_hash = mob->vnum % MAX_KEY_HASH; mob_next = mob->next; if (top_vnum_mob < mob->vnum) top_vnum_mob = mob->vnum; if (mob_hash != i) { if (!mob_prev) mob_index_hash[i] = mob->next; else mob_prev->next = mob->next; mob->next = mob_index_hash[mob_hash]; mob_index_hash[mob_hash] = mob; } else mob_prev = mob; } } /* rebuild obj index hash */ top_vnum_obj = 0; for (i = 0; i < MAX_KEY_HASH; i++) { OBJ_INDEX_DATA *obj, *obj_next, *obj_prev = NULL; for (obj = obj_index_hash[i]; obj; obj = obj_next) { int obj_hash = obj->vnum % MAX_KEY_HASH; obj_next = obj->next; if (top_vnum_obj < obj->vnum) top_vnum_obj = obj->vnum; if (obj_hash != i) { if (!obj_prev) obj_index_hash[i] = obj->next; else obj_prev->next = obj->next; obj->next = obj_index_hash[obj_hash]; obj_index_hash[obj_hash] = obj; } else obj_prev = obj; } } /* rebuild room index hash */ top_vnum_room = 0; for (i = 0; i < MAX_KEY_HASH; i++) { ROOM_INDEX_DATA *room, *room_next, *room_prev = NULL; for (room = room_index_hash[i]; room; room = room_next) { int room_hash = room->vnum % MAX_KEY_HASH; room_next = room->next; if (top_vnum_room < room->vnum) top_vnum_room = room->vnum; if (room_hash != i) { if (!room_prev) room_index_hash[i] = room->next; else room_prev->next = room->next; room->next = room_index_hash[room_hash]; room_index_hash[room_hash] = room; } else room_prev = room; } } pArea->max_vnum += delta; touch_area(pArea); char_puts("AreaEd: Changed areas:\n", ch); for (pArea = area_first; pArea; pArea = pArea->next) if (IS_SET(pArea->flags, AREA_CHANGED)) char_printf(ch, "[%3d] %s (%s)\n", pArea->vnum, pArea->name, pArea->file_name); return TRUE; } /* Local functions */ /***************************************************************************** Name: check_range(lower vnum, upper vnum) Purpose: Ensures the range spans only one area. Called by: areaed_vnum(olc_act.c). ****************************************************************************/ AREA_DATA *check_range(AREA_DATA *this, int ilower, int iupper) { AREA_DATA *pArea; for (pArea = area_first; pArea; pArea = pArea->next) { if (pArea == this || !pArea->min_vnum || !pArea->max_vnum) continue; if (IN_RANGE(ilower, pArea->min_vnum, pArea->max_vnum) || IN_RANGE(iupper, pArea->min_vnum, pArea->max_vnum) || IN_RANGE(pArea->min_vnum, ilower, iupper) || IN_RANGE(pArea->max_vnum, ilower, iupper)) return pArea; } return NULL; } static void move_mob(MOB_INDEX_DATA *mob, AREA_DATA *pArea, int delta) { bool touched = FALSE; MPTRIG *mp; int old_vnum = mob->vnum; MOVE(mob->vnum); if (mob->pShop) MOVE(mob->pShop->keeper); for (mp = mob->mptrig_list; mp; mp = mp->next) MOVE(mp->vnum); // MOVE(mob->fvnum); /* touch area if it is not area being moved */ if (touched && !IN_RANGE(old_vnum, pArea->min_vnum, pArea->max_vnum)) touch_vnum(old_vnum); } static void move_obj(OBJ_INDEX_DATA *obj, AREA_DATA *pArea, int delta) { bool touched = FALSE; int old_vnum = obj->vnum; /* fix containers */ switch (obj->item_type) { case ITEM_CONTAINER: MOVE(obj->value[2]); if (touched) { OBJ_DATA *o; for (o = object_list; o; o = o->next) if (o->pIndexData == obj) o->value[2] += delta; } } MOVE(obj->vnum); /* touch area if it is not area being moved */ if (touched && !IN_RANGE(old_vnum, pArea->min_vnum, pArea->max_vnum)) touch_vnum(old_vnum); } static void move_room(ROOM_INDEX_DATA *room, AREA_DATA *pArea, int delta) { int i; bool touched = FALSE; int old_vnum = room->vnum; RESET_DATA *r; MOVE(room->vnum); for (i = 0; i < MAX_DIR; i++) { EXIT_DATA *pExit = room->exit[i]; if (!pExit || !pExit->to_room.r) continue; if (IN_RANGE(pExit->to_room.r->vnum, pArea->min_vnum+delta, pArea->max_vnum+delta)) touched = TRUE; // Welesh : added for connected areas conversion if (IN_RANGE(pExit->to_room.r->vnum, pArea->min_vnum, pArea->max_vnum)) { pExit->to_room.r->vnum += delta; touched = TRUE; } // end-added } for (r = room->reset_first; r; r = r->next) { switch (r->command) { case 'M': case 'O': case 'P': MOVE(r->arg1); MOVE(r->arg3); break; case 'G': case 'E': case 'D': case 'R': MOVE(r->arg1); break; } } /* touch area if it is not area being moved */ if (touched && !IN_RANGE(old_vnum, pArea->min_vnum, pArea->max_vnum)) touch_vnum(old_vnum); }