-
Notifications
You must be signed in to change notification settings - Fork 0
/
deadlist.cp
214 lines (183 loc) · 8.75 KB
/
deadlist.cp
1
/****************************************************************************************//* DEADLIST.CP *//****************************************************************************************//* (c) 1995 by Magnet Interactive Studios, inc. All rights reserved. *//****************************************************************************************//* Revision History: *//* v5.6 5/5/95 Icebreaker Golden Master version. By Andrew Looney. *//****************************************************************************************//***************************** WHAT THIS SOFTWARE DOES ********************************** The purpose of this class is to provide an easy and dynamic way to display and maintain the animation that is played when an object of some sort is destroyed. Like all other objects, a death scene must be inserted into the giant linked list of solid objects implemented by the solids class, in order to force all of the objects to be drawn to the screen in the right order to provide the proper feeling of depth. However, unlike most other solids, death scenes will be constantly changing and then removed from the list on their own schedule. Thus, an easy way of managing these death scenes was needed. The way in which this is accomplished is to create a new object whenever a death scene is to be played and to keep it on a special list (in addition to the solids list) until the scene is done. It is assumed that master copies of all possible death animations are already loaded using the anim_source class; given this, we can dynamically create objects of the anim_user class and link them to the requested master copy, and then add the current cel of the anim_user entity to the solids_list for display. In addition, we also add the animation to our own linked list, so that we can easily keep track of any number of active death scene animations, update the frames as needed, and then deallocate the anim_user object when the animation has run its course.*****************************************************************************************//***** includes (make sure CPlusSwiHack.h is the last one) *****/#include "graphics.h"#include "stdio.h"#include "stdlib.h"#include "mem.h"#include "types.h"#include "hardware.h"#include "event.h"#include "strings.h"#include "access.h"#include "UMemory.h"#include "Form3DO.h"#include "Init3DO.h"#include "Parse3DO.h"#include "Utils3DO.h"#include "audio.h"#include "music.h"/***** Magnet includes *****/#include "icebreaker.h"#include "animation.h"#include "solids.h"#include "deadlist.h"/***** special c++ include (this must be last) *****/#include "CPlusSwiHack.h"/***** global class instantiations *****/extern solids population;/************************ dead_list::InitializeMorgue ********************************* This function handles all setup and initialization of variables that are used by this class. It is intended to be used repeatedly, at the start of each round of the game.*****************************************************************************************/void dead_list::InitializeMorgue (void){ morgue_list = (corpse *) NULL;}/************************ dead_list::CreateDeathScene ********************************* As the name implies, this function creates a death scene. Given a pointer to the master copy of the death scene animation, we grab some new memory, create an anim_user object, add the current frame to the solids list, and add the anim_user object to the list of death scenes (called morgue_list).*****************************************************************************************/void dead_list::CreateDeathScene (anim_source *original, int32 frame_rate, int32 x_position, int32 y_position, int32 cd_x, int32 cd_y, int32 starting_frame){ corpse *new_corpse,*traversal_ptr; new_corpse = new(corpse); new_corpse->death_scene.InitializeAnim (original, frame_rate); new_corpse->next = (corpse *) NULL; new_corpse->death_scene.PositionAnim(x_position,y_position); new_corpse->death_scene.Restart(); new_corpse->death_scene.current_frame_number = starting_frame; new_corpse->death_scene.RefetchFrame(); population.AddToList(new_corpse->death_scene.current_frame_ccb,DEATH_SCENE,cd_x,cd_y); if (morgue_list == (corpse *) NULL) morgue_list = new_corpse; else { traversal_ptr = morgue_list; while (traversal_ptr->next != (corpse *) NULL) traversal_ptr = traversal_ptr->next; traversal_ptr->next = new_corpse; }}/************************ dead_list::MaintainMorgue *********************************** This function must be called during every pass through the game. Given a list of death scene animations, we go through the list advancing the frame of each animation and checking to see if it's reached it's conclusion. If an animation has finished, we tell the solids_list to destroy the death scene object, and then we pull the anim_user out of our own linked list and deallocate the memory it was using. Lastly, if any animations are still active, we return TRUE. We return FALSE if no scenes are playing, so that if someone is waiting until the final death is played out, they'll know when the show ends.*****************************************************************************************/bool dead_list::MaintainMorgue(void){ corpse *traversal_ptr,*lagging_ptr; if (morgue_list == (corpse *) NULL) return(FALSE); traversal_ptr = lagging_ptr = morgue_list; while (traversal_ptr != (corpse *) NULL) { if (traversal_ptr->death_scene.AnimComplete()) { /* the scene is done, get rid of it */ population.EliminateObject(traversal_ptr->death_scene.current_frame_ccb); if (traversal_ptr == morgue_list) { morgue_list = morgue_list->next; traversal_ptr->death_scene.ShutdownForRestart(); delete(traversal_ptr); traversal_ptr = lagging_ptr = morgue_list; } else { lagging_ptr->next = traversal_ptr->next; traversal_ptr->death_scene.ShutdownForRestart(); delete(traversal_ptr); traversal_ptr = lagging_ptr->next; } } else /* the scene ain't done, advance frame and keep going */ { traversal_ptr->death_scene.AdvanceFrame(); lagging_ptr = traversal_ptr; traversal_ptr = traversal_ptr->next; } } return(TRUE);}/******************** dead_list::AdjustPositionOfNewDeath ****************************** This function forces a given death scene to be positioned on the solids list such thatit is visually in front of the given solid object or behind the given object.*****************************************************************************************/void dead_list::AdjustPositionOfNewDeath(solid_object *obstruction, bool last_first){ corpse *new_death; solid_object *new_death_object; if (morgue_list == (corpse *) NULL) return; new_death = morgue_list; while (new_death->next != (corpse *) NULL) new_death = new_death->next; new_death_object = population.FindPointerIntoList (new_death->death_scene.current_frame_ccb); if ((obstruction->object_type == PHANTOM_BOULDER) && (last_first)) { while ((obstruction->previous != (solid_object *) NULL) && (obstruction->previous->object_type == DEATH_SCENE)) obstruction = obstruction->previous; if ((obstruction->previous == (solid_object *) NULL) || (obstruction->previous->object_type > LAST_BOULDER) || (obstruction->previous->object_type < BOULDER0)) printf("Yikes! We didn't find a real boulder behind a phantom boulder!\n"); else obstruction = obstruction->previous; } population.TamperWithSorting(obstruction,new_death_object,last_first);}/*********************** dead_list::ShutdownForRestart ******************************** When a game ends, the player will either wish to quit or play again. In either case,this function should be called to surrender memory that was dynamically allocated duringthe game. Needless to say, it is particularly important that this function be calledafter every game; otherwise the memory that was used cannot be re-allocated.*****************************************************************************************/void dead_list::ShutdownForRestart(void){ corpse *traversal_ptr,*vanguard_pointer; traversal_ptr = morgue_list; while (traversal_ptr != (corpse *) NULL) { vanguard_pointer = traversal_ptr->next; population.EliminateObject(traversal_ptr->death_scene.current_frame_ccb); traversal_ptr->death_scene.ShutdownForRestart(); delete(traversal_ptr); traversal_ptr = vanguard_pointer; }}/************************************** EOF *********************************************/