/*****************************************************************************/ /* Template for version 2.0 plugins. */ /* Contact: yann.chachkoff@myrealbox.com */ /*****************************************************************************/ /* That code is placed under the GNU General Public Licence (GPL) */ /* (C)2001-2005 by Chachkoff Yann (Feel free to deliver your complaints) */ /*****************************************************************************/ /* CrossFire, A Multiplayer game for X-windows */ /* */ /* Copyright (C) 2008 the Crossfire development team */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* */ /*****************************************************************************/ /** * @defgroup plugin_rhg Random house generation plugin * This plugin links unused exits to random maps. * The random map parameters vary based on the map it is in, but each exit will always use * the same random seed to have the same layout and content. * * Exits will only point to a random map if both their @ref obj::slaying "slaying" and * @ref obj::msg "msg" fields are empty. * * @todo * - make more parameters vary based on maps * - add exits to all towns * * @{ */ /** * @file * This file is part of the @ref plugin_rhg "random house generation plugin". * See this page for more information. */ #include #include #include #ifndef __CEXTRACT__ #include #endif /** Link between a map and the exits to generate for it. */ typedef struct house_zone_struct { const char *mappath; /**< Full map path. */ const char *monsterstyle; /**< Style of monsters. */ } house_zone_struct; /** Maps we work on. */ static const house_zone_struct zones[] = { /* Scorn */ { "/world/world_104_115", "city" }, { "/world/world_105_115", "city" }, { "/world/world_104_116", "city" }, { "/world/world_105_116", "city" }, /* Navar */ { "/world/world_122_116", "city" }, { "/world/world_121_116", "city" }, { "/world/world_122_117", "city" }, { "/world/world_121_117", "city" }, { NULL, NULL } }; /** * Get the random map parameters of a map. * @param map * map to get the zone of. * @return * NULL if the map shouldn't be processed, else its parameters. */ static const house_zone_struct *get_map_zone(const mapstruct *map) { int zone; for (zone = 0; zones[zone].mappath != NULL; zone++) { if (strcmp(zones[zone].mappath, map->path) == 0) return &zones[zone]; } return NULL; } /** * Should we add a random map to this exit? * @param exit * exit to check. * @return * 1 if a map should be set, 0 else. */ static int is_suitable_exit(object *exit) { assert(exit); if (cf_object_get_int_property(exit, CFAPI_OBJECT_PROP_TYPE) != EXIT) return 0; if (cf_object_get_sstring_property(exit, CFAPI_OBJECT_PROP_SLAYING) || cf_object_get_sstring_property(exit, CFAPI_OBJECT_PROP_MESSAGE)) return 0; return 1; } /** * Get the random map seed. Will always yield the same value for the same (position included) exit. * @param exit * exit to get the seed of. * @param map * map the exit is on. * @return * random seed. */ static int get_exit_seed(const object *exit, const mapstruct *map) { char r[500]; int seed = 0, len, w = 0; snprintf(r, sizeof(r), "%s!%d,%d*%s", exit->arch->name, exit->x, exit->y, map->path); len = strlen(r)-1; while (len >= 0) { seed ^= ((int)r[len])<monsterstyle, get_exit_seed(exit, map)); cf_object_set_string_property(exit, CFAPI_OBJECT_PROP_SLAYING, "/!"); cf_object_set_string_property(exit, CFAPI_OBJECT_PROP_MESSAGE, params); } /** * Checks if the map should be processed, and if so process it. * @param map * map to work on. */ static void add_exits_to_map(const mapstruct *map) { int x, y; object *item; const house_zone_struct *zone = get_map_zone(map); if (!zone) return; for (x = 0; x < MAP_WIDTH(map); x++) { for (y = 0; y < MAP_HEIGHT(map); y++) { item = GET_MAP_OB(map, x, y); while (item) { if (is_suitable_exit(item)) add_exit_to_item(item, zone, map); item = item->above; } } } } /** * Global server event handling. Only uses EVENT_MAPLOAD. * @param type * unused. * @return * pointer to integer with value 0. */ CF_PLUGIN void *cfrhg_globalEventListener(int *type, ...) { va_list args; static int rv = 0; mapstruct *map; int code; va_start(args, type); code = va_arg(args, int); rv = 0; switch (code) { case EVENT_MAPLOAD: map = va_arg(args, mapstruct *); add_exits_to_map(map); break; } va_end(args); return &rv; } /** * Unused. * @param type * unused. * @return * NULL. */ CF_PLUGIN void *eventListener(int *type, ...) { return NULL; } /** * Plugin initialization. * @param iversion * server version. * @param gethooksptr * function to get hooks. * @return * 0. */ CF_PLUGIN int initPlugin(const char *iversion, f_plug_api gethooksptr) { cf_init_plugin(gethooksptr); cf_log(llevDebug, PLUGIN_VERSION " init\n"); return 0; } /** * Get the plugin identification or full name. * @param type * unused. * @return * NULL. */ CF_PLUGIN void *getPluginProperty(int *type, ...) { va_list args; const char *propname; int size; char *buf; va_start(args, type); propname = va_arg(args, const char *); if (!strcmp(propname, "Identification")) { buf = va_arg(args, char *); size = va_arg(args, int); va_end(args); snprintf(buf, size, PLUGIN_NAME); return NULL; } else if (!strcmp(propname, "FullName")) { buf = va_arg(args, char *); size = va_arg(args, int); va_end(args); snprintf(buf, size, PLUGIN_VERSION); return NULL; } va_end(args); return NULL; } /** * Unused. * @param op * unused. * @param params * unused. * @return * -1. */ CF_PLUGIN int cfrhg_runPluginCommand(object *op, char *params) { return -1; } /** * Plugin initialisation. * @return * 0. */ CF_PLUGIN int postInitPlugin(void) { cf_log(llevDebug, PLUGIN_VERSION " post init\n"); cf_system_register_global_event(EVENT_MAPLOAD, PLUGIN_NAME, cfrhg_globalEventListener); return 0; } /** * Unloading of plugin. * @return * 0. */ CF_PLUGIN int closePlugin(void) { cf_log(llevDebug, PLUGIN_VERSION " closing\n"); return 0; } /*@}*/