#include "munga.h" #pragma hdrstop #include "scnrole.h" #include "app.h" #include "notation.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ScenarioRole::ScenarioRole(const CString &role_name) { damageReceivedModifier = 0.0f; damageInflictedModifier = 0.0f; damageBias = 0.0f; friendlyFirePenalty = 0.0f; killBonus = 0.0f; roleName = role_name; returnFromDeath = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ScenarioRole::ScenarioRole(const CString &role_name, const CString &model_file) { Check_Pointer(&role_name); Check_Pointer(&model_file); roleName = role_name; // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Truncate the Role:: from roleName //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ResourceFile *res = application->GetResourceFile(); ResourceDescription *player_res_des; player_res_des = res->FindResourceDescription( model_file, ResourceDescription::GameModelResourceType ); if (player_res_des) { player_res_des->Lock(); ModelResource *player_data = (ModelResource *)player_res_des-> resourceAddress; killBonus = player_data->killBonus; specialCaseDeathPenalty = player_data->specialCaseDeathPenalty; // BT 4.10 (restored) returnFromDeath = player_data->returnFromDeath; damageReceivedModifier = player_data->damageReceivedModifier; damageInflictedModifier = player_data->damageInflictedModifier; damageBias = player_data->damageBias; friendlyFirePenalty = player_data->friendlyFirePenalty; player_res_des->Unlock(); // SCORE PROVENANCE (ungated, 2026-08-07). Every unmatched row of the // original manual's scoring chart -- +500 a kill, -1000 an eject, -500 // an ammo death -- is sourced HERE, from the role's GameModel record // (type 0xf, 7 dwords; the binary's ctor @00429a9c copies rec[0..6]). // A field log showed `charge=0 (role killBonus)`, and the two ways that // happens -- record authored zero, or resource lookup missed -- are // indistinguishable in release because the miss path's Warn/Tell compile // out (DEBUGOFF.h). One line per role settles it. DEBUG_STREAM << "[role] '" << (const char *)role_name << "' model='" << (const char *)model_file << "' killBonus=" << (float)killBonus << " deathPenalty=" << (float)specialCaseDeathPenalty << " dmgInf=" << (float)damageInflictedModifier << " dmgRcv=" << (float)damageReceivedModifier << " bias=" << (float)damageBias << " ff=" << (float)friendlyFirePenalty << " return=" << (int)returnFromDeath << "\n" << std::flush; } else { DEBUG_STREAM << "[role] '" << (const char *)role_name << "' model='" << (const char *)model_file << "' -- RESOURCE NOT FOUND, all score values default to 0" << "\n" << std::flush; Tell(role_name); Warn(" does not exists in resource! "); damageReceivedModifier = 0.0f; damageInflictedModifier = 0.0f; damageBias = 0.0f; friendlyFirePenalty = 0.0f; killBonus = 0.0f; specialCaseDeathPenalty = 0.0f; // BT 4.10 (restored) returnFromDeath = 0; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Scalar ScenarioRole::CalcDamageReceivedScore(const Scalar &damage_received) { Check(this); // ] //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Calculate modified score for the player receiving damage // damageReceived * damageReceivedModifier //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Check(this); Check_Fpu(); return -(damage_received * GetDamageReceivedModifier()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ScenarioRole::~ScenarioRole() { } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ResourceDescription::ResourceID ScenarioRole::CreateModelResource( #if DEBUG_LEVEL>0 ResourceFile *resource_file, const char* model_name, NotationFile * model_file, const ResourceDirectories *directories, ModelResource *model #else ResourceFile *resource_file, const char* model_name, NotationFile * model_file, const ResourceDirectories *, ModelResource *model #endif ) { 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); } //---------------------------------------- // Read in the data from notation file //---------------------------------------- // // Get PointValue assigned to this ScoreZone // if( !model_file->GetEntry( "gamedata", "KillBonus", &local_model->killBonus ) ) { std::cerr << model_name << "Missing KillBonus" << std::endl; Dump_And_Die: if (!model) { Unregister_Pointer(local_model); delete local_model; } return -1; } // BT 4.10: read right after KillBonus, fail-hard like every other key // (binary role reader @00429bec, dest = record slot [1]). if( !model_file->GetEntry( "gamedata", "SpecialCaseDeathPenalty", &local_model->specialCaseDeathPenalty ) ) { std::cerr << model_name << "Missing SpecialCaseDeathPenalty" << std::endl; goto Dump_And_Die; } if( !model_file->GetEntry( "gamedata", "DamageReceivedModifier", &local_model->damageReceivedModifier ) ) { std::cerr << model_name << "Missing DamageReceivedModifier" << std::endl; goto Dump_And_Die; } if( !model_file->GetEntry( "gamedata", "DamageInflictedModifier", &local_model->damageInflictedModifier ) ) { std::cerr << model_name << "Missing DamageInflictedModifier" << std::endl; goto Dump_And_Die; } if( !model_file->GetEntry( "gamedata", "ReturnFromDeath", &local_model->returnFromDeath ) ) { std::cerr << model_name << "Missing ReturnFromDeath" << std::endl; goto Dump_And_Die; } if( !model_file->GetEntry( "gamedata", "DamageBias", &local_model->damageBias ) ) { std::cerr << model_name << "Missing DamageBias" << std::endl; goto Dump_And_Die; } if( !model_file->GetEntry( "gamedata", "FriendlyFirePenalty", &local_model->friendlyFirePenalty ) ) { std::cerr << model_name << "Missing FriendlyFirePenalty" << std::endl; goto Dump_And_Die; } 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_Fpu(); Check(new_res); return new_res->resourceID; } else { Check_Fpu(); return 0; } }