/* * 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: Object * Description: - */ #define Uses_Ui #define Uses_Util #define Uses_ProgramManager #define Uses_DataFile #define Uses_Area #define Uses_Event #include "mheader.h" #include "object.h" #define OBJECT_BOX_BUFFER_SIZE 64 #define OBJECT_TYPE_NAME_SIZE 32 #define OBJECT_SUBTYPE_NAME_SIZE 16 #define OBJECT_ATTRIBUTE_NAME_SIZE 32 static OBJECT_INDEX name_to_object_index(const char *); static void * object_data_new(void); static void object_data_free(void *); /* * object type names */ static const char ObjectTypeName[MAX_OBJECT_TYPES] [OBJECT_TYPE_NAME_SIZE] = { "Close combat weapon", "Ranged combat weapon", "Armour", "Drug", "Environment", "Money", "Jump pack", "Tome" }; /* * object subtype names */ static const char ObjectSubtypeName[MAX_OBJECT_SUBTYPES] [OBJECT_SUBTYPE_NAME_SIZE] = { "Knife", "Pistol", "Basic", "Light", "Medium", "Heavy", "Ancient tome", "Warp tome", "Elevator", "Way up", "Way down" }; /* * object attribute names */ static const char ObjectAttributeName[MAX_OBJECT_ATTRIBUTES] [OBJECT_ATTRIBUTE_NAME_SIZE] = { "Alien", "Automatic recharge", "Blocks line of sight", "Daemonic", "Dangerous", "Environmental protection", "Force", "Force channel", "Force rune", "Hinders movement", "Ignore armour", "Impassable", "Inherent", "Laser", "Noisy", "No parry", "Pain", "Partial reload", "Plague", "Plasma", "Poison", "Power", "Projectile", "Psychic bolt", "Reliable", "Shock", "Silent", "Strength boost", "Strength boost II", "Unique" }; /* * the object box */ static BOX * ObjectBox = NULL; /* * direct link to object data for fast accesss */ static void ** ObjectData; /* * object data template (default values) */ static const OBJECT_DATA ObjectDataTemplate = { /* NAME */ "", /* NUMERUS */ NUMERUS_SINGULAR, /* SYMBOL */ '!', /* COLOUR */ {C_DEFAULT, C_NIL, 0}, /* DESCRIPTION */ "", /* ATTRIBUTES */ {false,false,false,false, false,false,false,false,false,false,false,false,false,false,false, false,false,false,false,false,false,false,false,false,false,false, false,false,false,false}, /* CONDITION_MAX */ CONDITION_INDESTRUCTABLE, /* CHARGE_MAX */ CHARGE_NIL, /* TYPE */ OTYPE_NIL, /* SUBTYPE */ OSTYPE_NIL, /* WEIGHT */ WEIGHT_NIL, /* VALUE */ VALUE_NIL, /* DAMAGE */ {0, 0, 0}, /* FIRING_MODE_DATA */ {{false, false, false}, 0, 0, 0, 0}, /* RELOAD_VALUE */ 0, /* REACH */ 0, /* PARRY_PENALTY */ 0, /* ARMOUR_VALUE */ 0 }; /* * Object module init */ void object_init(void) { ObjectBox = box_new(object_data_new, object_data_free, OBJECT_BOX_BUFFER_SIZE ); } /* * Object module clean up */ void object_clean_up(void) { if (ObjectBox != NULL) { box_free(ObjectBox); } } /* * adds an object to the object box */ OBJECT_DATA * object_box_new_object(void) { return box_new_item(ObjectBox); } /* * optimizes the object box */ void object_box_optimize(void) { box_optimize(ObjectBox); ObjectData = ObjectBox->item; } /* * allocs an object */ void * object_new(void) { return checked_malloc(sizeof(OBJECT)); } /* * frees an object */ void object_free(void *p) { free(p); } /* * creates an object (name based) */ OBJECT * object_create(const char *object_name) { OBJECT_INDEX object_index; OBJECT *object; object_index = name_to_object_index(object_name); object = object_create_i(object_index); return object; } /* * creates an object (index based) */ OBJECT * object_create_i(OBJECT_INDEX object_index) { OBJECT *object; const OBJECT_DATA *object_data; object_data = ObjectData[object_index]; object = object_new(); object->index = object_index; object->colour = dynamic_colour(&object_data->colour); object->gore_level = GORE_LEVEL_ZERO; object->condition = object_data->condition_max; object->charge = object_data->charge_max; object->functional = true; object->list_node = NULL; object->list_index = LIST_NODE_INDEX_NIL; return object; } /* * destroys an object * i.e. free + handling the complex data management mess */ void object_destroy(void *p) { OBJECT *object; object = (OBJECT *)p; if (object->list_node != NULL) { LIST *object_events; object_events = list_new(); remove_object(object, object_events); list_free_with(object_events, event_destroy); } object_free(object); } /* * produces an identical copy of an object */ OBJECT * object_clone(const OBJECT *object) { OBJECT *clone; clone = object_new(); *clone = *object; return clone; } /* * the object screen */ void object_screen(const OBJECT *object) { command_bar_set(1, CM_EXIT); render_object_screen(object); update_screen(); command_bar_get_command(); } /* * the object attribute screen */ void object_attribute_screen(OBJECT_ATTRIBUTE attribute) { command_bar_set(1, CM_EXIT); render_object_attribute_screen(attribute); update_screen(); command_bar_get_command(); } /* * returns the static data of an object */ const OBJECT_DATA * object_static_data(const OBJECT *object) { return ObjectData[object->index]; } /* * returns true if the passed object has the passed attribute */ bool object_has_attribute(const OBJECT *object, OBJECT_ATTRIBUTE attribute) { const OBJECT_DATA *object_data; object_data = ObjectData[object->index]; return object_data->attribute[attribute]; } /* * returns the description of an object attribute */ char * object_attribute_description(char *description, OBJECT_ATTRIBUTE attribute ) { return data_file_object_attribute_description(description, attribute ); } /* * returns the name of an object type */ const char * object_type_name(OBJECT_TYPE object_type) { return ObjectTypeName[object_type]; } /* * returns the name of an object subtype */ const char * object_subtype_name(OBJECT_SUBTYPE object_subtype) { return ObjectSubtypeName[object_subtype]; } /* * returns the name of an object attribute */ const char * object_attribute_name(OBJECT_ATTRIBUTE object_attribute) { return ObjectAttributeName[object_attribute]; } /* * name -> object type */ OBJECT_TYPE name_to_object_type(const char *name) { OBJECT_TYPE i; for (i = 0; i < MAX_OBJECT_TYPES; i++) { if (strings_equal(name, ObjectTypeName[i])) { return i; } } die("*** CORE ERRROR *** invalid object type: %s", name); /* NEVER REACHED */ return OTYPE_NIL; } /* * name -> object subtype */ OBJECT_SUBTYPE name_to_object_subtype(const char *name) { OBJECT_SUBTYPE i; for (i = 0; i < MAX_OBJECT_SUBTYPES; i++) { if (strings_equal(name, ObjectSubtypeName[i])) { return i; } } die("*** CORE ERROR *** invalid object subtype: %s", name); /* NEVER REACHED */ return OSTYPE_NIL; } /* * name -> object attribute */ OBJECT_ATTRIBUTE name_to_object_attribute(const char *name) { OBJECT_ATTRIBUTE i; for (i = 0; i < MAX_OBJECT_ATTRIBUTES; i++) { if (strings_equal(name, ObjectAttributeName[i])) { return i; } } die("*** CORE ERROR *** invalid object attribute: %s", name); /* NEVER REACHED */ return OA_NIL; } /* * if character equals NULL a list of all drug objects is returned, * otherwise a list of all drug objects present in the passed * character's inventory is returned */ LIST * object_list_drugs(CHARACTER *character) { LIST *list; LIST_NODE *node; list = list_new(); if (character == NULL) { int i; for (i = 0; i < ObjectBox->current_size; i++) { const OBJECT_DATA *object_data; object_data = ObjectData[i]; if (object_data->type == OTYPE_DRUG) { list_add(list, object_create_i(i)); } } return list; } for (node = character->inventory->head; node != NULL; node = node->next) { OBJECT *object; object = (OBJECT *)node->data; if (object_static_data(object)->type == OTYPE_DRUG){ list_add(list, object); } } return list; } /* * name -> object index */ static OBJECT_INDEX name_to_object_index(const char *name) { OBJECT_INDEX i; for (i = 0; i < ObjectBox->current_size; i++) { const OBJECT_DATA *object_data; object_data = ObjectData[i]; if (strings_equal(name, object_data->name)) { return i; } } die("*** CORE ERROR *** invalid object: %s", name); /* NEVER REACHED */ return OBJECT_INDEX_NIL; } /* * allocs object data */ static void * object_data_new(void) { OBJECT_DATA *object_data; object_data = checked_malloc(sizeof *object_data); *object_data = ObjectDataTemplate; return object_data; } /* * frees object data */ static void object_data_free(void *data) { free(data); }