#include "AdeptHeaders.hpp" #include "EntityManager.hpp" #include "RendererManager.hpp" #include "Application.hpp" #include "Tool.hpp" #include #include //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Entity__CreateMessage::ConstructCreateMessage(Script *script) { Check_Object(script); // //-------------- // Set up stream //-------------- // MemoryStream *message_stream = script->messageStream; Check_Object(message_stream); message_stream->AllocateBytes(sizeof(Entity__CreateMessage)); Replicator__CreateMessage::ConstructCreateMessage(script); Entity__CreateMessage *message = Cast_Pointer( Entity__CreateMessage*, message_stream->GetPointer() ); message->messageLength = sizeof(*message); // //--------------------------------------------------------------- // Point at the notation file and make other files relative to it //--------------------------------------------------------------- // Page *page = script->instancePage; Check_Object(page); Check_Object(Tool::Instance); Tool::Instance->PushFilePath(page->GetNotationFile()); // //--------------- // Read the flags //--------------- // bool flag = false; page->GetEntry("TileBound", &flag); if (flag) message->replicatorFlags |= Entity::TileBoundFlag; // //------------- //Get Alignment //------------- // const char *alignment_text; int alignment_value = Entity::DefaultAlignment; if(page->GetEntry("Alignment", &alignment_text)) alignment_value = Entity::AlignmentTextToAscii(alignment_text); message->alignment = alignment_value; // //---------------------------------------------------- // Find out the GameModel we need to build and open it //---------------------------------------------------- // Entity::ClassData *class_data; { const char* model_name; page->GetEntry("Model", &model_name, true); Resource resource; class_data = Tool::Instance->ConstructDataList(&resource, model_name); Check_Object(&resource); Verify(resource.DoesResourceExist()); message->dataListID = resource.GetResourceID(); } // //------------------------------------------------------------------------- // If this entity is a collider, make sure that it has a solid volume entry // in the game model //------------------------------------------------------------------------- // if ((message->replicatorFlags&Entity::AlwaysCollidesMask) != Entity::NeverCollidesMask) { Resource model_res; Entity::GetGameModelResourceFromDataListID( &model_res, message->dataListID ); Verify(model_res.DoesResourceExist()); Entity::GameModel *game_model = Cast_Pointer(Entity::GameModel*, model_res.GetPointer()); Check_Object(game_model); if (game_model->obbStreamResourceID == ResourceID::Null) message->replicatorFlags &= ~Entity::AlwaysCollidesMask; } // //------------------------------- // Deal with the initial position //------------------------------- // Point3D translation = Point3D::Identity; page->GetEntry("Translation", &translation); YawPitchRoll rotation = YawPitchRoll::Identity; page->GetEntry("Rotation", &rotation); message->localToParent.BuildTranslation(translation); message->localToParent.BuildRotation(rotation); // //------------------------- // Save the execution state //------------------------- // Entity::ExecutionStateEngine::FactoryRequest::Script state_script; Check_Object(class_data); Verify(class_data->IsDerivedFrom(Entity::DefaultData)); state_script.engineClass = class_data->executionStateClass; Check_Object(state_script.engineClass); state_script.instancePage = page; state_script.stateEngineName = "ExecutionState"; message->executionState.ConstructFactoryRequest(&state_script); Tool::Instance->PopFilePath(); // //---------------------------------- // Set the initial age of the entity //---------------------------------- // message->initialAge = 0.0f; page->GetEntry("Age", &message->initialAge); // //------------------------- //Save the instance name id //------------------------- // message->nameID = NameTable::NullObjectID; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Entity::SaveInstanceText(Page *page) { Check_Object(this); Check_Object(page); // //-------------------- // Save the Model Name //-------------------- // Check_Object(&gameModelResource); page->SetEntry("Model", (const char *)GetModelName()); // //------------------------- // Save the Execution State //------------------------- // if(executionState) { int execution_state = executionState->GetState(); MString execution_state_text; switch(execution_state) { case ExecutionStateEngine::NeverExecuteState: { execution_state_text = "NeverExecuteState"; break; } case ExecutionStateEngine::ExecuteOnceState: { execution_state_text = "ExecuteOnceState"; break; } case ExecutionStateEngine::AlwaysExecuteState: { execution_state_text = "AlwaysExecuteState"; break; } default: { #if defined(_ARMOR) if(*instanceName) { PAUSE(("Execution State for %s has not been defined", (const char *)instanceName)); } #endif execution_state_text = "NeverExecuteState"; break; } } page->SetEntry("ExecutionState", execution_state_text); } else { page->SetEntry("ExecutionState", "NeverExecuteState"); } // //-------------------------- // Save all the Entity Flags //-------------------------- // page->SetEntry("TileBound", IsTileBound()); // //--------------------------------------------------- // Save the Translation and Rotation in String format //--------------------------------------------------- // Point3D local_translation(GetLocalToParent()); page->SetEntry("Translation", local_translation); YawPitchRoll rotation_value(GetLocalToParent()); page->SetEntry("Rotation", rotation_value); const char *alignment_text; alignment_text = Entity::AlignmentAsciiToText(alignment); page->SetEntry("Alignment", alignment_text); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Entity__GameModel::ConstructGameModel(Script *script) { Check_Object(script); // //-------------- // Set up stream //-------------- // MemoryStream *model_stream = script->modelStream; Check_Object(model_stream); model_stream->AllocateBytes(sizeof(Entity__GameModel)); Entity__GameModel *model = Cast_Pointer(Entity__GameModel*, model_stream->GetPointer()); // //-------------------- // Set up the class ID //-------------------- // Entity::ClassData *class_data = script->modelClassData; Check_Object(class_data); model->classID = class_data->GetClassID(); NotationFile *model_file = script->modelFile; Check_Object(model_file); Page *page = model_file->GetPage("GameData"); Check_Object(page); // //------------------------------------------- // Read the element in from the notation file //------------------------------------------- // gos_PushCurrentHeap(ElementRenderer::GroupElement::s_Heap); ElementRenderer::Element *element = new ElementRenderer::GroupElement(); Check_Object(element); unsigned state=element->GetElementState(), delta; OBB bounds; ElementRenderer::Element::ReadStateFromPage( page, *MString::s_Empty, &state, &delta, &bounds ); ElementRenderer::StateChange *states = new ElementRenderer::StateChange(page, *MString::s_Empty); Check_Object(states); // //------------------------------- // Write the data out to a stream //------------------------------- // DynamicMemoryStream element_stream; state &= ~ElementRenderer::Element::CullMask; state |= ElementRenderer::Element::RootMode | ElementRenderer::Element::MatrixDirtyFlag; element_stream << state << bounds; states->Save(&element_stream); Check_Object(states); delete states; gos_PopCurrentHeap(); // //----------------------------------------- // Save the element stream in the resources //----------------------------------------- // MString element_name = model_file->GetFileName(); element_name += "{Element}"; Resource element_resource(element_name); element_resource.Save(&element_stream, Resource::ParentFileDependencies); Verify(element_resource.DoesResourceExist()); model->elementResourceID = element_resource.GetResourceID(); // //----------------------------------------- // Clear out the collision OBB resource IDs //----------------------------------------- // model->obbStreamResourceID = ResourceID::Null; if (class_data->obbFactory != NULL) (*class_data->obbFactory)(script); Check_Object(element); delete element; // //------------------------------------------- // Spin Through all the game model attributes //------------------------------------------- // ModelAttributeEntry *attribute_entry; TableIteratorOf iterator( &class_data->gameModelAttributeTable.attributesByID); int num_attributes = iterator.GetSize(); int i; for(i=Entity__GameModel::AnyAttributeID + 1;igameModelAttributeTable.GetAttributeEntry(i); Check_Object(attribute_entry); const char *data = ""; page->GetEntry(attribute_entry->attributeName, &data); char *error_message; error_message = new char[128]; strcpy(error_message, ""); Check_Pointer(error_message); if(!(*class_data->modelVerifier)(model, attribute_entry, data, &error_message, 128)) { STOP(("%s Game Model Error : %s", model_file->GetFileName(), error_message)); } Check_Pointer(error_message); delete [] error_message; } // //------------------------ // Set the collision flags //------------------------ // model->defaultFlags = 0; if(model->collider) model->defaultFlags |= Entity::ColliderFlag; if(model->canBeWalkedOn) model->defaultFlags |= Entity::CanBeWalkedOnFlag|Entity::CanBeShotFlag; if(model->canBeShot) model->defaultFlags |= Entity::CanBeShotFlag; if(model->waterSurface) model->defaultFlags |= Entity::WaterSurfaceFlag; if(model->OBBCollides) model->defaultFlags |= Entity::OBBCollidesFlag; if (model->defaultFlags == Entity::OBBCollidesFlag) model->defaultFlags = 0; const char *walk_thru_string; if(page->GetEntry("WalkThruFlag", &walk_thru_string)) { model->defaultFlags |= WalkThruTextToAscii(walk_thru_string); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Entity__GameModel::ConstructOBBStream(Script *script) { Check_Object(script); // //-------------- // Set up stream //-------------- // MemoryStream *model_stream = script->modelStream; Check_Object(model_stream); Entity__GameModel *model = Cast_Pointer(Entity__GameModel*, model_stream->GetPointer()); // //------------------------------ // See if there is an OBB stream //------------------------------ // NotationFile *model_file = script->modelFile; Check_Object(model_file); Page *page = model_file->GetPage("GameData"); Check_Object(page); const char* obb_stream_name; if (!page->GetEntry("SolidOBB", &obb_stream_name)) return; // //-------------------------------------------------------- // There is, so now we have to stuff it into the resources //-------------------------------------------------------- // Check_Pointer(obb_stream_name); FileStream obb_stream(obb_stream_name); const char* file_name = obb_stream.GetFileName(); Resource res(file_name); if (!res.DoesResourceExist() || !res.IsResourceUpToDate()) { FileDependencies obb_dependencies; obb_dependencies.AddDependency(&obb_stream); res.Save(&obb_stream, &obb_dependencies); if (!res.IsRegistered()) Resource::ParentFileDependencies->AddDependencies(&obb_dependencies); } else if (!res.IsRegistered()) res.AddFileDependenciesTo(Resource::ParentFileDependencies); model->obbStreamResourceID = res.GetResourceID(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool Entity__GameModel::ReadAndVerify( Entity__GameModel *model, ModelAttributeEntry *attribute_entry, const char *data, char **error, int error_buffer ) { Check_Object(attribute_entry); bool result = false; bool valid_data = (*data != '\0'); // //---------------------------------------- //This is the Genric Type read in Section. //---------------------------------------- // if(valid_data) { switch(attribute_entry->attributeType) { case ScalarClassID: { Scalar value = AtoF(data); attribute_entry->SetValue(model, &value); result = true; break; } case Vector3DClassID: { Vector3D value; int entries = sscanf( data, "%f %f %f", &value.x, &value.y, &value.z ); if(entries != 3) { _snprintf( *error, error_buffer, "{[GameData]%s=%s}Bad Vector Value", (char *)attribute_entry->attributeName, data ); return false; } attribute_entry->SetValue(model, &value); result = true; break; } case IntClassID: { int value = atoi(data); attribute_entry->SetValue(model, &value); result = true; break; } case BoolClassID: { bool value = (!_stricmp(data, "true") || !_stricmp(data, "yes") || atoi(data) != 0); attribute_entry->SetValue(model, &value); result = true; break; } case RadianClassID: { Radian value = AtoF(data); value = value * Stuff::Radians_Per_Degree; attribute_entry->SetValue(model, &value); result = true; break; } case Point3DClassID: { Point3D value; int entries; entries = sscanf( data, "%f %f %f", &value.x, &value.y, &value.z ); if(entries != 3) { _snprintf( *error, error_buffer, "{[GameData]%s=%s}Bad Point Value", (char *)attribute_entry->attributeName, data ); return false; } attribute_entry->SetValue(model, &value); result = true; break; } case RGBAColorClassID: { RGBAColor value; int entries; entries = sscanf( data, "%f %f %f %f", &value.red, &value.green, &value.blue, &value.alpha ); if (entries == 3) { value.alpha = 1.0f; } if (entries < 3) { _snprintf( *error, error_buffer, "{[GameData]%s=%s}Bad RGBAColor Value", (char *)attribute_entry->attributeName, data ); return false; } attribute_entry->SetValue(model, &value); result = true; break; } case UnitQuaternionClassID: { //Read in a quaternion as a YawpitchRoll angle UnitQuaternion value; YawPitchRoll yaw_pitch_roll; int entries; entries = sscanf( data, "%f %f %f", &yaw_pitch_roll.yaw.angle, &yaw_pitch_roll.pitch.angle, &yaw_pitch_roll.roll.angle ); if(entries != 3) { _snprintf( *error, error_buffer, "{[GameData]%s=%s}Bad Angle Value", (char *)attribute_entry->attributeName, data ); return false; } yaw_pitch_roll.yaw *= Radians_Per_Degree; yaw_pitch_roll.pitch *= Radians_Per_Degree; yaw_pitch_roll.roll *= Radians_Per_Degree; value = yaw_pitch_roll; value.Normalize(); attribute_entry->SetValue(model, &value); result = true; break; } case CharClassID: { char *value; value = new char[MaxStringLength]; Check_Pointer(value); Str_Copy(value, data, MaxStringLength); attribute_entry->SetValue(model, value); result = true; Check_Pointer(value); delete value; break; } case ResourceIDClassID: { const char* resource_name = (const char *)data; const char* resource_extension = strrchr(resource_name, '.'); // resource_extension == NULL is a valid value. if(resource_extension && !_stricmp(resource_extension, ".data")) { // //------------------------------------------------ //If we are a .data file then Create us as a model //------------------------------------------------ // Resource model_resource; Tool::Instance->ConstructDataList(&model_resource, resource_name); Check_Object(&model_resource); Verify(model_resource.DoesResourceExist()); attribute_entry->SetValue(model, (void *)&model_resource.GetResourceID()); result = true; } else if(resource_extension && !_stricmp(resource_extension, ".instance")) { NotationFile instance_file(resource_name); Resource instance_resource; ReplicatorID base_id = ReplicatorID::Null; Check_Object(Tool::Instance); Tool::Instance->ConstructCreateMessage( &instance_resource, &instance_file, &base_id ); Verify(instance_resource.DoesResourceExist()); attribute_entry->SetValue(model, (void *)&instance_resource.GetResourceID()); result = true; } else { ResourceID default_id = ResourceID::Null; attribute_entry->SetValue(model, (void *)&default_id); result = true; } break; } } } switch(attribute_entry->attributeID) { case ColliderAttributeID: { if(!valid_data) { bool value = false; attribute_entry->SetValue(model,&value); result = true; } } break; case CanBeShotAttributeID: { if(!valid_data) { bool value = false; attribute_entry->SetValue(model,&value); result = true; } } break; case CanBeWalkedOnAttributeID: { if(!valid_data) { bool value = false; attribute_entry->SetValue(model,&value); result = true; } } break; case WaterSurfaceAttributeID: { if(!valid_data) { bool value = false; attribute_entry->SetValue(model,&value); result = true; } } break; case OBBCollidesAttributeID: { if(!valid_data) { bool value = true; attribute_entry->SetValue(model,&value); result = true; } } break; } return result; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Entity__GameModel::WriteToText( Entity__GameModel *model, ModelAttributeEntry *attribute_entry, char **text_string ) { Check_Object(attribute_entry); Check_Pointer(model); switch(attribute_entry->attributeType) { case ScalarClassID: { Scalar value; attribute_entry->GetValue((Entity__GameModel *)model, &value); sprintf( *text_string, "%.2f", value ); break; } case RadianClassID: { Radian value; attribute_entry->GetValue((Entity__GameModel *)model, &value); value = value * Stuff::Degrees_Per_Radian; sprintf( *text_string, "%.2f", value.angle ); break; } case IntClassID: { int value; attribute_entry->GetValue((Entity__GameModel *)model, &value); sprintf( *text_string, "%d", value ); break; } case Vector3DClassID: { Vector3D value; attribute_entry->GetValue((Entity__GameModel *)model, &value); sprintf( *text_string, "%.2f %.2f %.2f", value.x, value.y, value.z ); break; } case BoolClassID: { bool value; attribute_entry->GetValue((Entity__GameModel *)model, &value); if(value) { strcpy(*text_string, "yes"); } else { strcpy(*text_string, "no"); } break; } case Point3DClassID: { Point3D value; attribute_entry->GetValue((Entity__GameModel *)model, &value); sprintf( *text_string, "%.2f %.2f %.2f", value.x, value.y, value.z ); break; } case RGBAColorClassID: { RGBAColor value; attribute_entry->GetValue((Entity__GameModel *)model, &value); sprintf( *text_string, "%.2f %.2f %.2f %.2f", value.red, value.green, value.blue, value.alpha ); break; } case UnitQuaternionClassID: { UnitQuaternion value; YawPitchRoll yaw_pitch_roll; attribute_entry->GetValue((Entity__GameModel *)model, &value); yaw_pitch_roll = value; sprintf( *text_string, "%.2f %.2f %.2f", yaw_pitch_roll.yaw, yaw_pitch_roll.pitch, yaw_pitch_roll.roll ); break; } case ResourceIDClassID: { ResourceID value; attribute_entry->GetValue((Entity__GameModel *)model, &value); char path[256],*p; if(value != ResourceID::Null) { Resource resource(value); strcpy(path,resource.GetName()); p = strrchr(path,'{'); if (p) p = 0; p = strrchr(path,'.'); if (!stricmp(p,".data")) { sprintf(*text_string,"Content\\%s",path); } } else { strcpy(path, "NULL"); sprintf(*text_string,"%s",path); } break; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Entity__GameModel::SaveGameModel( Entity__GameModel *model, Stuff::NotationFile *data_file ) { Check_Object(model); Check_Object(data_file); // //--------------------------------------------------------------- //First we need to spin through our attributes and write them out //--------------------------------------------------------------- // ModelAttributeEntry *attribute_entry; Entity__ClassData *class_data; class_data = (Entity__ClassData *)Entity::FindClassData(model->classID); TableIteratorOf iterator( &class_data->gameModelAttributeTable.attributesByID); int num_attributes = iterator.GetSize(); int i; Page *page = data_file->SetPage("GameData"); Check_Object(page); page->SetEntry("Class",class_data->GetClassName()); //This is temp for right now...eventually we will need a text write function in element if(model->elementResourceID != ResourceID::Null) { Resource element_resource(model->elementResourceID); Verify(element_resource.DoesResourceExist()); //We need to yank out the cull mode from this stream unsigned element_state; element_resource >> element_state; if (element_state & ElementRenderer::Element::BoundsLockedFlag) { page->SetEntry("Cull", "NeverCull"); } } for(i=Entity__GameModel::AnyAttributeID + 1;igameModelAttributeTable.GetAttributeEntry(i); Check_Object(attribute_entry); char* data = new char [Entity__GameModel::MaxStringLength]; Register_Pointer(data); class_data->modelWriteToText(model, attribute_entry, &data); page->SetEntry(attribute_entry->attributeName,data); Unregister_Pointer(data); delete [] data; } int flags = model->defaultFlags; if(flags & Entity::HeavyCanWalkThruType) page->SetEntry("WalkThruFlag", "HeavyCanWalkThru"); else if(flags & Entity::MediumCanWalkThruType) page->SetEntry("WalkThruFlag", "MediumCanWalkThru"); else if(flags & Entity::AnythingCanWalkThruType) page->SetEntry("WalkThruFlag", "AnythingCanWalkThru"); // //-------------------------------------------------------- //Now we need to save out the specific non attribute stuff //-------------------------------------------------------- // #if 0 if(obbStreamResourceID != ResourceID::Null) { Resource obb_resource(obbStreamResourceID); Verify(obb_resource.DoesResourceExist()); data_file->SetEntry("GameData", #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // const char * Entity::AlignmentAsciiToText(int alignment) { switch(alignment) { case Player: return "Player"; case Enemy: return "Enemy"; case Team1: return "Team1"; case Team2: return "Team2"; case Team3: return "Team3"; case Team4: return "Team4"; } return "Default"; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Entity::AlignmentTextToAscii(const char *alignment) { if(!_stricmp(alignment, "Player")) return Player; else if(!_stricmp(alignment, "Enemy")) return Enemy; else if(!_stricmp(alignment, "Team1")) return Team1; else if(!_stricmp(alignment, "Team2")) return Team2; else if(!_stricmp(alignment, "Team3")) return Team3; else if(!_stricmp(alignment, "Team4")) return Team4; return DefaultAlignment; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Entity__GameModel::GetEffectResourceID(ResourceID *return_id, const ResourceID& effect_stream, BYTE index) { ResourceID *effect_array; Resource effect_resource(effect_stream); Verify(effect_resource.DoesResourceExist()); BYTE material_count; effect_resource >> material_count; if (material_count <= index) { *return_id = ResourceID::Null; return; } effect_array = Cast_Pointer(ResourceID *, effect_resource.GetPointer()); *return_id = effect_array[index]; #if defined(_ARMOR) if(*return_id != ResourceID::Null) { Resource verify_resource(*return_id); Verify(verify_resource.DoesResourceExist()); } #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int Entity__GameModel::WalkThruTextToAscii(const char *string) { if(!_stricmp(string, "NothingCanWalkThru")) return Entity::NothingCanWalkThruType; else if(!_stricmp(string, "HeavyCanWalkThru")) return Entity::HeavyCanWalkThruType; else if(!_stricmp(string, "MediumCanWalkThru")) return Entity::MediumCanWalkThruType; else if(!_stricmp(string, "AnythingCanWalkThru")) return Entity::AnythingCanWalkThruType; else STOP(("Walk Thru Type: %s is not valid", string)); return 0; }