#include "rp.h" #pragma hdrstop #include "scorzone.h" #include "..\munga\fileutil.h" #include "..\munga\nttmgr.h" #include "..\munga\app.h" #include "..\munga\hostmgr.h" #include "..\munga\notation.h" //############################################################################# //############################### ScoreZone ############################# //############################################################################# //############################################################################# // Shared Data Support // Derivation* ScoreZone::GetClassDerivations() { static Derivation classDerivations(Entity::GetClassDerivations(), "ScoreZone"); return &classDerivations; } ScoreZone::SharedData ScoreZone::DefaultData( ScoreZone::GetClassDerivations(), ScoreZone::MessageHandlers, ScoreZone::GetAttributeIndex(), ScoreZone::StateCount, (Entity::MakeHandler)ScoreZone::Make ); //############################################################################# // Attribute Support // const ScoreZone::IndexEntry ScoreZone::AttributePointers[]= { ATTRIBUTE_ENTRY(ScoreZone, ScoreZoneType, scoreZoneType), ATTRIBUTE_ENTRY(ScoreZone, PointValue, pointValue) }; ScoreZone::AttributeIndexSet& ScoreZone::GetAttributeIndex() { static ScoreZone::AttributeIndexSet attributeIndex(ELEMENTS(ScoreZone::AttributePointers), ScoreZone::AttributePointers, Entity::GetAttributeIndex() ); return attributeIndex; } //############################################################################# // Message Support // const Receiver::HandlerEntry ScoreZone::MessageHandlerEntries[]= { MESSAGE_ENTRY(ScoreZone, ProcessScoreZoneRequest) }; Receiver::MessageHandlerSet ScoreZone::MessageHandlers( ELEMENTS(ScoreZone::MessageHandlerEntries), ScoreZone::MessageHandlerEntries, Entity::GetMessageHandlers() ); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ScoreZone::ProcessScoreZoneRequestMessageHandler( ProcessScoreZoneRequestMessage *message ) { Check(this); Check_Pointer(message); // //---------------------------------------- // Make sure that the score zone is active //---------------------------------------- // EntityGroup *score_zone_group; if (GetSimulationState() == Active) { // //----------------------------------------------------------- // If Sequential, hunt for ourselves in the sequential group //----------------------------------------------------------- // Check(application); EntityManager *entity_mgr = application->GetEntityManager(); Check(entity_mgr); if ( scoreZoneType == LocalSequential || scoreZoneType == GlobalSequential ) { int new_zone = sequenceNumber + 1; score_zone_group = entity_mgr->FindGroup("SequentialScoreZones"); Check(score_zone_group); ChainIteratorOf iterator(score_zone_group->groupMembers); ScoreZone *score_zone, *first_score_zone = NULL; // //------------------------------------------------------------------ // Store the first score zone in case we run off the end of the list //------------------------------------------------------------------ // while ((score_zone = (ScoreZone*)iterator.ReadAndNext()) != NULL) { Check(score_zone); if (score_zone->sequenceNumber == 1) { first_score_zone = score_zone; } if (score_zone->sequenceNumber == new_zone) { break; } } if (!score_zone) { score_zone = first_score_zone; } if (score_zone->GetSimulationState() == InActive) { score_zone->SetSimulationState(Active); score_zone_group = entity_mgr->FindGroup("ActiveScoreZones"); Check(score_zone_group); score_zone_group->Add(score_zone); } } // //---------------------------------------------------------------- // Set the zone as inactive, remove ourselves from the active list //---------------------------------------------------------------- // SetSimulationState(InActive); score_zone_group = entity_mgr->FindGroup("ActiveScoreZones"); Check(score_zone_group); ChainIteratorOf iterator(score_zone_group->groupMembers); ScoreZone *score_zone; while ((score_zone = (ScoreZone*)iterator.GetCurrent()) != NULL) { if (score_zone == this) { iterator.Remove(); break; } iterator.Next(); } // //----------------------------------- // Send the points back to the player //----------------------------------- // ReplyMessage reply( message->replyMessageID, sizeof(ReplyMessage), pointValue ); Check(application); HostManager *host = application->GetHostManager(); Check(host); Entity *entity = host->GetEntityPointer(message->requestingEntity); Check(entity); entity->Dispatch(&reply); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ScoreZone::Dispatch(Receiver::Message *message) { Check(this); Check(message); ProcessScoreZoneRequestMessage *score_zone_message = (ProcessScoreZoneRequestMessage*) message; if (score_zone_message->messageID == ProcessScoreZoneRequestMessageID) { if (!extentBox.Contains(score_zone_message->linearPosition)) { Check_Fpu(); return; } } Entity::Dispatch(score_zone_message); Check_Fpu(); } //############################################################################# // Construction and Destruction // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ScoreZone::ScoreZone( ScoreZone::MakeMessage *creation_message, ScoreZone::SharedData &virtual_data ): Entity(creation_message, virtual_data) { Check_Pointer(this); Check_Pointer(creation_message); SetValidFlag(); //------------------------------------------------- // Find the drop zone resource in the resource file //------------------------------------------------- ResourceFile *res_file = application->GetResourceFile(); Check(res_file); ResourceDescription *res = res_file->SearchList( resourceID, ResourceDescription::GameModelResourceType ); Check(res); res->Lock(); // // Get ScoreZone Info // sequenceNumber = creation_message->sequenceNumber; ModelResource *score_res = (ModelResource*)res->resourceAddress; scoreZoneType = score_res->scoreZoneType; pointValue = score_res->pointValue; extentBox = score_res->extentBox; extentBox.minX += localOrigin.linearPosition.x; extentBox.minY += localOrigin.linearPosition.y; extentBox.minZ += localOrigin.linearPosition.z; extentBox.maxX += localOrigin.linearPosition.x; extentBox.maxY += localOrigin.linearPosition.y; extentBox.maxZ += localOrigin.linearPosition.z; SetSimulationState(InActive); res->Unlock(); //--------------------------------------------------------------------- // Make the sequential score zone list. Only make the first sequential // score zone active //--------------------------------------------------------------------- EntityManager *entity_manager = application->GetEntityManager(); Check(entity_manager); EntityGroup *score_zones; if (scoreZoneType == LocalSequential || scoreZoneType == GlobalSequential) { score_zones = entity_manager->UseGroup("SequentialScoreZones"); Check(score_zones); score_zones->Add(this); if (sequenceNumber == 1) { goto Active_Zone; } } // //------------------------------------------------ // If it isn't a sequential, always make it active //------------------------------------------------ // else { Active_Zone: score_zones = entity_manager->UseGroup("ActiveScoreZones"); Check(score_zones); SetSimulationState(Active); score_zones->Add(this); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ScoreZone* ScoreZone::Make(ScoreZone::MakeMessage *creation_message) { return new ScoreZone(creation_message); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical ScoreZone::CreateMakeMessage( MakeMessage *creation_message, NotationFile *model_file, const ResourceDirectories *directories ) { Check(creation_message); Check(model_file); if (!Entity::CreateMakeMessage(creation_message, model_file, directories)) { Check_Fpu(); return False; } creation_message->classToCreate = RegisteredClass::ScoreZoneClassID; creation_message->messageLength = sizeof(*creation_message); creation_message->instanceFlags = IndependantInstance|DynamicFlag|MapFlag|TrappedFlag; char *p; creation_message->sequenceNumber = -1; if ((p = strtok(NULL, " ")) != NULL) { creation_message->sequenceNumber = atoi(p); } Check_Fpu(); return True; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ScoreZone::~ScoreZone() { Check(this); if (scoreZoneType == LocalSequential || scoreZoneType == GlobalSequential) { Check(application); EntityManager *entity_mgr = application->GetEntityManager(); Check(entity_mgr); EntityGroup *score_zone_group = entity_mgr->FindGroup("SequentialScoreZones"); if (score_zone_group) { ChainIteratorOf iterator(score_zone_group->groupMembers); ScoreZone *score_zone = (ScoreZone*)iterator.GetCurrent(); if (score_zone == this) { iterator.Remove(); if (!iterator.GetCurrent()) { entity_mgr->RemoveGroup(score_zone_group); } } } } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ResourceDescription::ResourceID ScoreZone::CreateModelResource( ResourceFile *resource_file, const char* model_name, NotationFile * model_file, const ResourceDirectories *directories, ModelResource *model ) { Check(resource_file); Check_Pointer(model_name); Check_Pointer(directories); // // If we were not provided a buffer to write the model data into, we must // create it ourselves. Then make sure that the model stuff is read in // ModelResource *local_model = model; if (!local_model) { local_model = new ModelResource; Register_Pointer(local_model); } // // Get PointValue assigned to this ScoreZone // if( !model_file->GetEntry( "gamedata", "PointValue", &local_model->pointValue ) ) { std::cerr << model_name << "Missing PointValue" << std::endl; Dump_And_Die: if (!model) { Unregister_Pointer(local_model); delete local_model; } Check_Fpu(); return -1; } // // Get The ScoreZone Type // const char* score_zone_type; if( !model_file->GetEntry( "gamedata", "ScoreZoneType", &score_zone_type ) ) { std::cerr << model_name << "Missing ScoreZoneType" << std::endl; goto Dump_And_Die; } else { if(strcmp(score_zone_type,"GlobalOneTime") == 0) { local_model->scoreZoneType = GlobalOneTime; } else if(strcmp(score_zone_type,"LocalOneTime") == 0) { local_model->scoreZoneType = LocalOneTime; } else if(strcmp(score_zone_type,"GlobalSequential") == 0) { local_model->scoreZoneType = GlobalSequential; } else if(strcmp(score_zone_type,"LocalSequential") == 0) { local_model->scoreZoneType = LocalSequential; } } // // Read In the Extent Box from the solid file determined by the // collision data // const char* sld_entry; if( !model_file->GetEntry( "gamedata", "Extents", &sld_entry ) ) { std::cerr << model_name << "Missing .sld Specifications " << std::endl; goto Dump_And_Die; } else { char *sld_filename = MakePathedFilename(directories->collisionDirectory, sld_entry); Register_Pointer(sld_filename); NotationFile *sld_file = new NotationFile(sld_filename); Register_Object(sld_file); if(sld_file->PageCount() == 0) { std::cerr <MakeEntryList("volume 0","extm"); Register_Object(sld_namelist); if (sld_namelist->EntryCount() == 0) { Dump_And_Die_2: Unregister_Pointer(sld_filename); delete sld_filename; Unregister_Object(sld_file); delete sld_file; Unregister_Object(sld_namelist); delete sld_namelist; goto Dump_And_Die; } NameList::Entry *extent_entry = sld_namelist->GetFirstEntry(); while(extent_entry) { Scalar value = extent_entry->GetAtof(); if (strcmp(extent_entry->GetName(),"extminX") == 0) { local_model->extentBox.minX = value; } else if (strcmp(extent_entry->GetName(),"extminY") == 0) { local_model->extentBox.minY = value; } else if (strcmp(extent_entry->GetName(),"extminZ") == 0) { local_model->extentBox.minZ = value; } else if (strcmp(extent_entry->GetName(),"extmaxX") == 0) { local_model->extentBox.maxX = value; } else if (strcmp(extent_entry->GetName(),"extmaxY") == 0) { local_model->extentBox.maxY = value; } else if (strcmp(extent_entry->GetName(),"extmaxZ") == 0) { local_model->extentBox.maxZ = value; } else { std::cerr << sld_filename << "Improper Extent Format" << std::endl; goto Dump_And_Die_2; } extent_entry = extent_entry->GetNextEntry(); } Unregister_Pointer(sld_filename); delete sld_filename; Unregister_Object(sld_file); delete sld_file; Unregister_Object(sld_namelist); delete sld_namelist; } // //--------------------------- // Write out the new resource //--------------------------- // if (!model) { ResourceDescription *new_res = resource_file->AddResource( model_name, ResourceDescription::GameModelResourceType, 1, ResourceDescription::Preload, local_model, sizeof(*local_model) ); Unregister_Pointer(local_model); delete local_model; Check(new_res); Check_Fpu(); return new_res->resourceID; } else { Check_Fpu(); return 0; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical ScoreZone::TestInstance() const { return IsDerivedFrom(*GetClassDerivations()); }