/* * 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: Event * Description: This module is responsible for handling delayed events. */ #include #define Uses_Ui #define Uses_Equipment #define Uses_Util #define Uses_Grammar #define Uses_Drugs #define Uses_Psychic #define Uses_Effect #define Uses_Area #define Uses_Stats #include "mheader.h" #include "event.h" #define MAX_EVENT_TYPES 7 /* * resets the event queue */ #define event_queue_reset() EventQueueNextNode = area_event_list()->head; static EVENT * event_queue_next_event(void); static void event_queue_remove(const EVENT *); /* * event execution functions */ static void (* const EventFunction[MAX_EVENT_TYPES])(EVENT *) = { reload_weapon, recharge_weapon, unjam_weapon, effect_terminate_event, psy_power_terminate, drug_terminate, poison_damage, }; /* * the event which is currently being executed */ static EVENT * ExecutedEvent = NULL; /* * the next node in the event queue */ static LIST_NODE * EventQueueNextNode = NULL; /* * allocs an event */ void * event_new(void) { return checked_malloc(sizeof(EVENT)); } /* * frees an evnet */ void event_free(void *p) { free(p); } /* * creates an event */ EVENT * event_create(EVENT_TYPE type, PHASE_TIME delay) { EVENT *event; STAT i; event = event_new(); event->type = type; event->delay = delay; event->character = NULL; event->object = NULL; event->drug = DRUG_NIL; event->psy_power = PSY_NIL; event->effect = ET_NIL; event->power = 0; for (i = 0; i < MAX_STATS; i++) { event->stat_modifier[i] = 0; } return event; } /* * destroys an event * i.e. free + handling the complex data management mess */ void event_destroy(void *p) { event_free(p); } /* * sets an event */ void event_set(EVENT *event) { list_add(area_event_list(), event); } /* * handles events */ void handle_events(void) { EVENT *event; event_queue_reset(); while ((event = event_queue_next_event()) != NULL) { if (event->delay == TIME_UNDETERMINED) { continue; } if (event->delay == TIME_CONTINUOUS) { event_execute(event); continue; } event->delay -= 1; if (event->delay > 0) { continue; } event_execute(event); } } /* * executes an event */ void event_execute(EVENT *event) { ExecutedEvent = event; (*EventFunction[event->type])(event); if (ExecutedEvent == NULL) { return; } if (event->delay != TIME_CONTINUOUS) { event_queue_remove(event); event_destroy(event); } ExecutedEvent = NULL; } /* * removes a specific character event */ EVENT * remove_character_event(const CHARACTER *character, EVENT_TYPE event_type) { EVENT *event; event_queue_reset(); while ((event = event_queue_next_event()) != NULL) { if (event->type == event_type && event->character == character) { event_queue_remove(event); event_queue_reset(); return event; } } event_queue_reset(); return NULL; } /* * removes all events which contain a reference to the passed character */ void remove_character_events(const CHARACTER *character, LIST *character_events) { EVENT *event; event_queue_reset(); while ((event = event_queue_next_event()) != NULL) { if (event->character != character) { continue; } event_queue_remove(event); list_add(character_events, event); } event_queue_reset(); } /* * remove all events which contain a reference to the passed object */ void remove_object_events(const OBJECT *object, LIST *object_events) { EVENT *event; event_queue_reset(); while ((event = event_queue_next_event()) != NULL) { if (event->object != object) { continue; } event_queue_remove(event); list_add(object_events, event); } event_queue_reset(); } /* * remove all events which contain a reference to the passed terrain * object */ void remove_terrain_events(const TERRAIN *terrain, LIST *terrain_events) { /* no terrain events yet */ NOT_USED(terrain); NOT_USED(terrain_events); } /* * returns a pointer to a specific effect termination event */ EVENT * effect_termination_event(CHARACTER *character, EFFECT effect) { EVENT *event; bool event_found; event_queue_reset(); event_found = false; while ((event = event_queue_next_event()) != NULL) { if (event->type != EVT_EFFECT_TERMINATION) { continue; } if (event->character == character && event->effect == effect) { event_found = true; break; } } event_queue_reset(); if (!event_found) { return NULL; } return event; } /* * returns the next event in the event queue */ static EVENT * event_queue_next_event(void) { EVENT *event; if (EventQueueNextNode == NULL) { return NULL; } event = (EVENT *)EventQueueNextNode->data; EventQueueNextNode = EventQueueNextNode->next; return event; } /* * removes an event from the event queue */ static void event_queue_remove(const EVENT *event) { if (EventQueueNextNode != NULL && event == EventQueueNextNode->data) { EventQueueNextNode = EventQueueNextNode->next; } if (event == ExecutedEvent) { ExecutedEvent = NULL; } list_remove(area_event_list(), event); }