/* * Copyright (C) 2002-2007 The Warp Rogue Team * Part of the Warp Rogue Project * * This software is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License. * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY. * * See the license.txt file for more details. */ /* * Module Name: Terrain * Description: - */ #define Uses_Ui #define Uses_Area #define Uses_Util #define Uses_DataFile #define Uses_ProgramManager #define Uses_DynamicMessage #define Uses_Effect #define Uses_Object #define Uses_Character #define Uses_Event #include "mheader.h" #include "terrain.h" #define TERRAIN_BOX_BUFFER_SIZE 32 #define TERRAIN_ATTRIBUTE_NAME_SIZE 32 typedef int N_TERRAINS; static TERRAIN_INDEX name_to_terrain_index(const char *); static void * terrain_data_new(void); static void terrain_data_free(void *); /* * terrain attribute names */ static const char TerrainAttributeName[MAX_TERRAIN_ATTRIBUTES] [TERRAIN_ATTRIBUTE_NAME_SIZE] = { "Air", "Blocks line of sight", "Causes disease", "Dangerous", "Impassable" }; /* * the terrain box */ static BOX * TerrainBox = NULL; /* * direct link to terrain data for fast accesss */ static void ** TerrainData; /* * terrain data template (default values) */ static const TERRAIN_DATA TerrainDataTemplate = { /* NAME */ "", /* SYMBOL */ '.', /* COLOUR */ {C_DEFAULT, C_NIL, 0}, /* DESCRIPTION */ "", /* ATTRIBUTES */ {false,false,false,false, false} }; /* * Terrain module init */ void terrain_init(void) { TerrainBox = box_new(terrain_data_new, terrain_data_free, TERRAIN_BOX_BUFFER_SIZE ); } /* * Terrain module clean up */ void terrain_clean_up(void) { if (TerrainBox != NULL) { box_free(TerrainBox); } } /* * adds a terrain to the terrain box */ TERRAIN_DATA * terrain_box_new_terrain(void) { return box_new_item(TerrainBox); } /* * optimizes the terrain box */ void terrain_box_optimize(void) { box_optimize(TerrainBox); TerrainData = TerrainBox->item; } /* * allocs a terrain */ void * terrain_new(void) { return checked_malloc(sizeof(TERRAIN)); } /* * frees a terrain */ void terrain_free(void *p) { free(p); } /* * creates a terrain (name based) */ TERRAIN * terrain_create(const char *terrain_name) { TERRAIN_INDEX terrain_index; TERRAIN *terrain; terrain_index = name_to_terrain_index(terrain_name); terrain = terrain_create_i(terrain_index); return terrain; } /* * creates a terrain (index based) */ TERRAIN * terrain_create_i(TERRAIN_INDEX terrain_index) { TERRAIN *terrain; const TERRAIN_DATA *terrain_data; terrain_data = TerrainData[terrain_index]; terrain = terrain_new(); terrain->index = terrain_index; terrain->colour = dynamic_colour(&terrain_data->colour); terrain->gore_level = GORE_LEVEL_ZERO; terrain->list_node = NULL; terrain->list_index = LIST_NODE_INDEX_NIL; return terrain; } /* * destroys a terrain * i.e. free + handling the complex data management mess */ void terrain_destroy(void *p) { TERRAIN *terrain; terrain = (TERRAIN *)p; if (terrain->list_node != NULL) { LIST *terrain_events; terrain_events = list_new(); remove_terrain(terrain, terrain_events); list_free_with(terrain_events, event_destroy); } terrain_free(terrain); } /* * produces an identical copy of a terrain */ TERRAIN * terrain_clone(const TERRAIN *terrain) { TERRAIN *clone; clone = terrain_new(); *clone = *terrain; return clone; } /* * the terrain screen */ void terrain_screen(const TERRAIN *terrain) { command_bar_set(1, CM_EXIT); render_terrain_screen(terrain); update_screen(); command_bar_get_command(); } /* * the terrain attribute screen */ void terrain_attribute_screen(TERRAIN_ATTRIBUTE attribute) { command_bar_set(1, CM_EXIT); render_terrain_attribute_screen(attribute); update_screen(); command_bar_get_command(); } /* * returns the static data of a terrain */ const TERRAIN_DATA * terrain_static_data(const TERRAIN *terrain) { return TerrainData[terrain->index]; } /* * returns true if the passed terrain has the passed attribute */ bool terrain_has_attribute(const TERRAIN *terrain, TERRAIN_ATTRIBUTE attribute) { const TERRAIN_DATA *terrain_data; terrain_data = TerrainData[terrain->index]; return terrain_data->attribute[attribute]; } /* * returns the name of a terrain attribute */ const char * terrain_attribute_name(TERRAIN_ATTRIBUTE attribute) { return TerrainAttributeName[attribute]; } /* * returns the description of a terrain attribute */ char * terrain_attribute_description(char *description, TERRAIN_ATTRIBUTE attribute ) { return data_file_terrain_attribute_description(description, attribute ); } /* * disease causing terrain effect */ void terrain_cause_disease(CHARACTER *character) { if (character->armour != NULL) { if (object_has_attribute(character->armour, OA_ENVIRONMENTAL_PROTECTION)) { return; } } if (disease_resisted(character)) { if (character->party == PARTY_PLAYER) { dynamic_message(MSG_RESIST, character, NULL, MOT_NIL ); } } else { effect_activate(character, ET_DISEASED, TIME_UNDETERMINED); } } /* * returns true if the passed terrain is dangerous for the passed character */ bool terrain_dangerous_for(const CHARACTER *character, const TERRAIN *terrain) { const TERRAIN_DATA *terrain_data; terrain_data = terrain_static_data(terrain); if (terrain_data->attribute[TA_AIR]) { return true; } if (!terrain_data->attribute[TA_CAUSES_DISEASE]) { return false; } if (character->perk[PK_IMMUNITY_TO_DISEASE]) { return false; } if (character->armour != NULL) { if (object_has_attribute(character->armour, OA_ENVIRONMENTAL_PROTECTION)) { return false; } } return true; } /* * name -> terrain attribute */ TERRAIN_ATTRIBUTE name_to_terrain_attribute(const char *name) { TERRAIN_ATTRIBUTE i; for (i = 0; i < MAX_TERRAIN_ATTRIBUTES; i++) { if (strings_equal(name, TerrainAttributeName[i])) { return i; } } die("*** CORE ERROR *** invalid terrain attribute: %s", name); /* NEVER REACHED */ return TA_NIL; } /* * name -> terrain attribute */ static TERRAIN_INDEX name_to_terrain_index(const char *name) { TERRAIN_INDEX i; for (i = 0; i < TerrainBox->current_size; i++) { const TERRAIN_DATA *terrain_data; terrain_data = TerrainData[i]; if (strings_equal(name, terrain_data->name)) { return i; } } die("*** CORE ERROR *** invalid terrain: %s", name); return TERRAIN_INDEX_NIL; } /* * allocs terrain data */ static void * terrain_data_new(void) { TERRAIN_DATA *terrain_data; terrain_data = checked_malloc(sizeof *terrain_data); *terrain_data = TerrainDataTemplate; return terrain_data; } /* * frees terrain data */ static void terrain_data_free(void *data) { free(data); }