/* * 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: Npc * Description: - */ #define Uses_Ui #define Uses_Character #define Uses_Faction #define Uses_Career #define Uses_Stats #define Uses_Util #define Uses_ProgramManager #define Uses_Psychic #define Uses_Perks #define Uses_Inventory #define Uses_Object #define Uses_Equipment #define Uses_Random #include "mheader.h" #include "npc.h" #define NPC_BOX_BUFFER_SIZE 64 static void * npc_new(void); static void npc_free(void *); static void npc_counter_clean_up(void); static void npc_randomize_stats(CHARACTER *); /* * the NPC box */ static BOX * NpcBox = NULL; /* * direct link to NPC data for fast accesss */ static void ** Npc; /* * the NPC counter */ static NPC_COUNTER * NpcCounter = NULL; /* * NPC counter template (default values) */ static const NPC_COUNTER NpcCounterTemplate = { /* N_SPAWNED */ 0, /* N_KILLED */ 0 }; /* * Npc module init */ void npc_init(void) { NpcBox = box_new(npc_new, npc_free, NPC_BOX_BUFFER_SIZE ); } /* * Npc module clean up */ void npc_clean_up(void) { if (NpcBox != NULL) { box_free(NpcBox); } npc_counter_clean_up(); } /* * adds a new NPC to the NPC box */ CHARACTER * npc_box_new_npc(void) { CHARACTER *npc; npc = box_new_item(NpcBox); npc->index = NpcBox->current_size - 1; return npc; } /* * optimizes the NPC box */ void npc_box_optimize(void) { box_optimize(NpcBox); Npc = NpcBox->item; } /* * returns the size of the NPC box */ N_CHARACTERS npc_box_size(void) { return NpcBox->current_size; } /* * inits the NPC counter */ void npc_counter_init(void) { NPC_INDEX i; NpcCounter = checked_malloc(NpcBox->current_size * sizeof *NpcCounter ); for (i = 0; i < NpcBox->current_size; i++) { NpcCounter[i] = NpcCounterTemplate; } } /* * returns the passed NPC's counter */ NPC_COUNTER * npc_counter(NPC_INDEX npc_index) { return &NpcCounter[npc_index]; } /* * creates an NPC (name based) */ CHARACTER * npc_create(const char *npc_name) { NPC_INDEX npc_index; CHARACTER *npc; npc_index = name_to_npc_index(npc_name); npc = npc_create_i(npc_index); return npc; } /* * creates an NPC (index based) */ CHARACTER * npc_create_i(NPC_INDEX npc_index) { CHARACTER *npc; npc = character_clone(Npc[npc_index]); if (!character_has_flag(npc, CF_UNIQUE) && !character_has_flag(npc, CF_MACHINE)) { npc_randomize_stats(npc); } return npc; } /* * returns true if the passed NPC is unique */ bool npc_is_unique(NPC_INDEX npc_index) { CHARACTER *npc; if (npc_index == NPC_RANDOM) { return false; } npc = Npc[npc_index]; return npc->flag[CF_UNIQUE]; } /* * returns the NPC's description */ const char * npc_description(NPC_INDEX npc_index) { CHARACTER *npc; if (npc_index == NPC_RANDOM) { return NULL; } npc = Npc[npc_index]; return npc->description; } /* * NPC index -> name */ const char * npc_index_to_name(NPC_INDEX npc_index) { const CHARACTER *npc; npc = Npc[npc_index]; return npc->name; } /* * name -> NPC index */ NPC_INDEX name_to_npc_index(const char *name) { NPC_INDEX i; if (strings_equal(name, "RANDOM_NPC")) { return NPC_RANDOM; } for (i = 0; i < NpcBox->current_size; i++) { const CHARACTER *npc; npc = Npc[i]; if (strings_equal(name, npc->name)) { return i; } } die("*** CORE ERROR *** invalid NPC: %s", name); return NPC_INDEX_NIL; } /* * allocates an NPC */ static void * npc_new(void) { CHARACTER *npc; npc = character_new(); npc->description = checked_malloc(DESCRIPTION_SIZE * sizeof *npc->description ); clear_string(npc->description); return npc; } /* * frees an NPC */ static void npc_free(void *p) { CHARACTER *npc; npc = (CHARACTER *)p; free(npc->description); character_free(npc); } /* * NPC counter clean up */ static void npc_counter_clean_up(void) { if (NpcCounter != NULL) { free(NpcCounter); } } /* * adds some random variation to a NPC's stats */ static void npc_randomize_stats(CHARACTER *character) { STAT i; for (i = 0; i < MAX_STATS; i++) { CHARACTER_STAT *stat; int p; stat = &character->stat[i]; if (stat->total == 0) { continue; } p = random_int(80, 120); stat->total = percent(p, stat->total); stat->current = stat->total; } }