/**
* @file zone.c
* @ingroup zone
*
* Zone based code
*
* @author Geoff Davis <geoff@circlemudsquared.org>
* @author Greg Buxton <greg@circlemudsquared.org>
*
* @par Copyright:
* Copyright (C) 2006 Geoff Davis <geoff@circlemudsquared.org><br>
* Greg Buxton <greg@circlemudsquared.org>
*
* @par
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University<br>
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.
*
* @par
* All rights reserved. See license.doc for complete information.
*
* @package cs
* @version 1.0
*/
#define __ZONE_C__
#include "sysdep.h"
#include "structs.h"
#include "interpreter.h"
#include "main.h"
#include "utils.h"
#include "dao.h"
#include "db.h"
#include "spells.h"
#include "room.h"
#include "extraDesc.h"
#include "item.h"
#include "mobile.h"
#include "shop.h"
/*
* This is here for now
*/
const char *reset_types[] = {
/* 00 */ "none",
/* 01 */ "loadMobile",
/* 02 */ "loadItem",
/* 03 */ "giveItemToMobile",
/* 04 */ "doorState",
/* 05 */ "purgeItem",
/* 06 */ "purgeMobile", /* new? */
/* 07 */ "equipMobile",
/* 08 */ "putItemInContainer",
"\n"
};
const char *equip_slots[] = {
"light",
"rightFinger",
"leftFinger",
"firstNeck",
"secondNeck",
"onBody",
"head",
"legs",
"feet",
"hands",
"arms",
"shield",
"aboutBody",
"waist",
"rightWrist",
"leftWrist",
"wielded",
"held",
"\n"
};
#define ZCMD_NONE (0)
#define ZCMD_LOADMOB (1)
#define ZCMD_LOADITEM (2)
#define ZCMD_GIVEITEM (3)
#define ZCMD_SETDOOR (4)
#define ZCMD_PURGEITEM (5)
#define ZCMD_PURGEMOB (6)
#define ZCMD_EQUIPMOB (7)
#define ZCMD_PUTITEM (8)
/*
* External variables.
*/
extern const char *zone_reset_types[];
extern struct shop_data *shop_index;
extern int top_shop;
/*
* Local function prototypes.
*/
bool zoneData_saveFile(zoneData_t *zone);
void zoneData_resetCommandToDao(daoData_t *dao, int n, resetCommand_t *cmd);
void keyword_zones(void) {
char keywords[120] = { '\0' };
int i = 0;
for (i = 0; i <= top_of_zone_table; i++) {
/* Ask for the keyword for the zone, new data */
log("\r\n:: Zone: %s", zone_table[i].name);
printf("Specify keyword for zone: ");
scanf("%s", keywords);
zone_table[i].keyword = strdup(keywords);
}
}
void world_toDao(void) {
zoneRnum_t rzone = NOWHERE;
/* Declare an iterator variable. */
register int i = 0;
log("Saving zones:\r\n");
/* Iterate each zone in the zone table. */
for (i = 0; i <= top_of_zone_table; i++) {
if (!zoneData_saveFile(&(zone_table[i]))) {
log("...Unable to save zone #%d.\r\n", zone_table[rzone].number);
}
}
log("...Done.\r\n");
}
/**
* Save a zone to disk in DAO format
* @param zone Zone to save
* @returns TRUE or FALSE
*/
bool zoneData_saveFile(zoneData_t *zone) {
bool retcode = FALSE;
/* Declare a variable to contain the filename. */
char filename[PATH_MAX] = { '\0' };
if (zone == NULL) {
log("zoneData_saveFile(): invalid 'zone' zoneData_t.");
} else if (!get_filename(filename, sizeof(filename), ZONE_FILE, zone->keyword)) {
log("zoneData_saveFile(): couldn't get filename for zone %s.", zone->keyword);
} else {
/* Declare an iterator variable. */
register int i = 0;
/* Declare some temporary DAO pointers. */
daoData_t *rootDao = NULL, *subContainerDao = NULL, *zoneDao = NULL;
rootDao = dao_newDocument();
zoneDao = dao_newChild(rootDao, "zone");
dao_newScalar(zoneDao, "name", "%s", zone->name);
dao_newScalar(zoneDao, "keyword", "%s", zone->keyword);
dao_newScalar(zoneDao, "lifespan", "%d", zone->lifespan);
if (zone->cmd && zone->cmd->command != 'S') {
/* Construct the 'resetList' container DAO. */
subContainerDao = dao_newChild(zoneDao, "resets");
/* Iterate over the zone's reset command list. */
for (i = 0; zone->cmd[i].command != 'S'; i++) {
/* Convert each zone command to its DAO representation. */
zoneData_resetCommandToDao(subContainerDao, i, &(zone->cmd[i]));
}
}
/* Set the subcontainer DAO back to NULL. */
subContainerDao = NULL;
/* Iterate over the rooms in the world table. */
for (i = 0; i <= top_of_world; i++) {
/* Skip rooms not contained by the specified zone. */
if (zone_table[world[i].zone].number != zone->number) {
continue;
}
/* Allocate the 'roomList' container DAO, if necessary. */
if (subContainerDao == NULL) {
subContainerDao = dao_newChild(zoneDao, "rooms");
}
/* Convert each room to its DAO representation. */
roomData_toDao(subContainerDao, &(world[i]));
}
/* Set the subcontainer DAO back to NULL. */
subContainerDao = NULL;
/* Iterate over the items in the obj_proto table */
for (i = 0; i <= top_of_objt; i++) {
/* Skip objects not in the specified zone. */
if (GET_OBJ_VNUM(&(obj_proto[i])) > zone->top ||
GET_OBJ_VNUM(&(obj_proto[i])) < zone->bot) {
continue;
}
/* Allocate the 'objectList' container DAO, if necessary. */
if (subContainerDao == NULL) {
subContainerDao = dao_newChild(zoneDao, "itemPrototypes");
}
/* Convert each item to it's DAO representation. */
itemData_toDao(subContainerDao, &(obj_proto[i]));
}
/* Set the subcontainer DAO back to NULL. */
subContainerDao = NULL;
/* Iterate over the mobiles in the mob_proto table */
for (i = 0; i <= top_of_mobt; i++) {
/* Skip mobiles not in the specified zone. */
if (GET_MOB_VNUM(&(mob_proto[i])) > zone->top ||
GET_MOB_VNUM(&(mob_proto[i])) < zone->bot) {
continue;
}
/* Allocate the 'mobileList' container DAO, if necessary. */
if (subContainerDao == NULL) {
subContainerDao = dao_newChild(zoneDao, "mobilePrototypes");
}
/* Convert each mobile to it's DAO representation. */
mobile_toDao(subContainerDao, &(mob_proto[i]));
}
/* Set the subcontainer DAO back to NULL. */
subContainerDao = NULL;
/* Iterate over the shops in the shop_index table */
for (i = 0; i <= top_shop; i++) {
if (shop_index[i].vnum > zone->top ||
shop_index[i].vnum < zone->bot) {
continue;
}
/* Allocate the 'mobileList' container DAO, if necessary. */
if (subContainerDao == NULL) {
subContainerDao = dao_newChild(zoneDao, "shops");
}
/* Convert each shop to it's DAO representation. */
shopData_toDao(subContainerDao, &(shop_index[i]));
}
/* Save the DAO out to disk. */
retcode = dao_saveFile(rootDao, filename);
/* Free the top-level DAO container. */
dao_free(rootDao);
}
return (retcode);
}
room_rnum real_room(room_vnum vnum);
extern const char *dirs[];
extern const char *wear_bits[];
int zoneNum_forVnum(int vnum) {
int zNum = 0;
for (zNum = 0; zNum <= top_of_zone_table; zNum++) {
if (zone_table[zNum].bot <= vnum && vnum <= zone_table[zNum].top)
return zNum;
}
return -1;
}
/**
* Convert a zone reset to its DAO representation.
* @param parentDao the container DAO to contain the reset's DAO
* @param n the index of the zone reset in the zone's reset list
* @param cmd the zone reset to be converted
* @return none
*/
void zoneData_resetCommandToDao(daoData_t *dao, int n, resetCommand_t *cmd) {
if (dao == NULL) {
log("zoneData_resetCommandToDao(): invalid 'dao' daoData_t.");
} else if (cmd == NULL) {
log("zoneData_resetCommandToDao(): invalid 'cmd' resetCommand_t.");
} else {
/* Declare a DAO pointer. */
daoData_t *resetDao = NULL;
/* Declare a temp variable */
int zResetType = 0;
resetDao = dao_newChild(dao, "%d", n);
/* Set the zone reset type. */
switch(cmd->command) {
case '*': zResetType = ZCMD_NONE; break;
case 'M': zResetType = ZCMD_LOADMOB; break;
case 'O': zResetType = ZCMD_LOADITEM; break;
case 'G': zResetType = ZCMD_GIVEITEM; break;
case 'D': zResetType = ZCMD_SETDOOR; break;
case 'R': zResetType = ZCMD_PURGEITEM; break;
case 'K': zResetType = ZCMD_PURGEMOB; break;
case 'E': zResetType = ZCMD_EQUIPMOB; break;
case 'P': zResetType = ZCMD_PUTITEM; break;
}
if (cmd->if_flag != 0)
dao_newScalar(resetDao, "then", "%s", YESNO(cmd->if_flag));
dao_newScalar(resetDao, "command", "%s", reset_types[zResetType]);
/*
* This is where things will get ugly...
*
* To make the reset commands human readable, we're outputting different
* tags based on the reset command. This means more work in the saving
* and loading, but a much better result for human editing.
*/
switch(zResetType) {
case ZCMD_NONE:
break;
case ZCMD_LOADMOB:
if (cmd->arg1 != 0)
dao_newScalar(resetDao, "mobile", "%s:%d", zone_table[(zoneNum_forVnum(cmd->arg1))].keyword, cmd->arg1);
if (cmd->arg3 != 0)
dao_newScalar(resetDao, "inRoom", "%s:%d", zone_table[(world[real_room(cmd->arg3)].zone)].keyword, cmd->arg3);
if (cmd->arg2 != 0)
dao_newScalar(resetDao, "maxNumber", "%d", cmd->arg2);
break;
case ZCMD_LOADITEM:
if (cmd->arg1 != 0)
dao_newScalar(resetDao, "item", "%s:%d", zone_table[(zoneNum_forVnum(cmd->arg1))].keyword, cmd->arg1);
if (cmd->arg3 != 0)
dao_newScalar(resetDao, "inRoom", "%s:%d", zone_table[(world[real_room(cmd->arg3)].zone)].keyword, cmd->arg3);
if (cmd->arg2 != 0)
dao_newScalar(resetDao, "maxNumber", "%d", cmd->arg2);
break;
case ZCMD_GIVEITEM:
if (cmd->arg1 != 0)
dao_newScalar(resetDao, "item", "%s:%d", zone_table[(zoneNum_forVnum(cmd->arg1))].keyword, cmd->arg1);
if (cmd->arg2 != 0)
dao_newScalar(resetDao, "maxNumber", "%d", cmd->arg2);
/* No arg3 for these */
break;
case ZCMD_SETDOOR:
if (cmd->arg2 >= 0 && cmd->arg2 <= NUM_OF_DIRS) {
if (cmd->arg1 != 0)
dao_newScalar(resetDao, "inRoom", "%s:%d", zone_table[(world[real_room(cmd->arg1)].zone)].keyword, cmd->arg1);
dao_newScalar(resetDao, "direction", "%s", dirs[cmd->arg2]);
switch(cmd->arg3) {
case 0:
dao_newScalar(resetDao, "state", "open");
break;
case 1:
dao_newScalar(resetDao, "state", "closed");
break;
case 2:
dao_newScalar(resetDao, "state", "locked");
break;
}
}
break;
case ZCMD_PURGEITEM:
if (cmd->arg1 != 0)
dao_newScalar(resetDao, "inRoom", "%s:%d", zone_table[(world[real_room(cmd->arg1)].zone)].keyword, cmd->arg1);
if (cmd->arg2 != 0)
dao_newScalar(resetDao, "item", "%s:%d", zone_table[(zoneNum_forVnum(cmd->arg2))].keyword, cmd->arg2);
/* No arg3 for these */
break;
case ZCMD_PURGEMOB:
if (cmd->arg1 != 0)
dao_newScalar(resetDao, "inRoom", "%s:%d", zone_table[(world[real_room(cmd->arg1)].zone)].keyword, cmd->arg1);
if (cmd->arg2 != 0)
dao_newScalar(resetDao, "mobile", "%s:%d", zone_table[(zoneNum_forVnum(cmd->arg2))].keyword, cmd->arg2);
/* No arg3 for these */
break;
case ZCMD_EQUIPMOB:
if (cmd->arg3 >= 0 && cmd->arg3 < NUM_WEARS) {
if (cmd->arg1 != 0)
dao_newScalar(resetDao, "item", "%s:%d", zone_table[(zoneNum_forVnum(cmd->arg1))].keyword, cmd->arg1);
dao_newScalar(resetDao, "wearLocation", "%s", equip_slots[cmd->arg3]);
if (cmd->arg2 != 0)
dao_newScalar(resetDao, "maxNumber", "%d", cmd->arg2);
}
break;
case ZCMD_PUTITEM:
if (cmd->arg1 != 0)
dao_newScalar(resetDao, "item", "%s:%d", zone_table[(zoneNum_forVnum(cmd->arg1))].keyword, cmd->arg1);
if (cmd->arg2 != 0)
dao_newScalar(resetDao, "maxNumber", "%d", cmd->arg2);
if (cmd->arg3 != 0)
dao_newScalar(resetDao, "inItem", "%s:%d", zone_table[(zoneNum_forVnum(cmd->arg3))].keyword, cmd->arg3);
break;
}
}
}