//===========================================================================//
// File:	btl4galm.cpp                                                        //
// Project: BattleTech          Brick: Gauge Renderer Manager                 //
// Contents: BTL4GaugeAlarmManager -- the BattleTech override of the MUNGA      //
//           GaugeAlarmManager.  It supplies the two per-item stream virtuals    //
//           that the base class declares pure ("not overridden!"): it knows how //
//           to compile a named cockpit-gauge alarm definition into a memory     //
//           stream (CreateGaugeAlarmStreamItem) and how to instantiate a live   //
//           GaugeAlarm for a given subsystem/condition from that stream         //
//           (ReadGaugeAlarmStreamItem).                                         //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 02/22/96  CPB  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved //
//                      PROPRIETARY AND CONFIDENTIAL                         //
//===========================================================================//
//
// RECONSTRUCTED -- IMPORTANT PROVENANCE NOTE
// ------------------------------------------
// btl4galm.obj links after btl4grnd.obj and before btl4vid.obj (BTL4.MAK
// BTL4_OBJS order).  In the shipped optimised image (BTL4OPT.EXE) there is **no
// distinct, separately-emitted BTL4GaugeAlarmManager override body**:
//   * the only GaugeAlarmManager code in the binary is the MUNGA base class in
//     gaugalrm.cpp (recovered/all/part_006.c, @00448928..@00448f48), including
//     the two "not overridden!" trap virtuals
//        CreateGaugeAlarmStreamItem  @00448ab8  (asserts GAUGALRM.CPP:0x71)
//        ReadGaugeAlarmStreamItem    @00448ad4  (asserts GAUGALRM.CPP:0x7e)
//     and the base driver helpers that CALL those virtuals
//        GaugeAlarmManager::CreateGaugeAlarmStream  @00448af0
//        GaugeAlarmManager::BuildAlarmsForModel     @00448d00
//   * no subclass vtable (one whose Create/Read slots point into BattleTech
//     code) appears in vtables.tsv, and no caller constructs a subclass
//     (the base ctors @00448ebd/@00448edc/@00448efb have no external callers).
// The code region the linker reserved for btl4galm.obj (@004cc40c..@004cdac0)
// actually holds a 3-D HUD-model builder (PNAME1..8.bgf), i.e. the compiler
// folded BTL4GaugeAlarmManager's tiny overrides away / it was never instantiated
// in this build configuration.
//
// This file is therefore reconstructed to MATCH THE SURVIVING BTL4GALM.HPP and
// the base driver's calling contract (the argument order, the GaugeAlarm object
// it expects, and the "undefined alarm type ... resource not built" diagnostic
// the base prints when the virtual returns False).  Bodies below are BEST-EFFORT
// (low confidence): they describe what the override must do for the base driver
// to function, not bytes lifted from this image.
//
// Base contract (recovered, high confidence):
//   GaugeAlarmManager::CreateGaugeAlarmStream @00448af0
//     - opens the "gaugeAlarm" sub-resource of a model record (FUN_00404720,
//       "gaugeAlarm" @004eecc9), counts its entries, makes a MemoryStream
//       (0x18), and for each entry calls the virtual
//         this->CreateGaugeAlarmStreamItem(stream, entry_name, entry_data)
//       (entry_name @entry+8, entry_data @entry[1]); if it returns 0 it prints
//         "Model file '<model>' has undefined alarm type '<name>' -
//          resource not built."   (strings @004eecd4/@004eece1/@004eecfe)
//       and aborts the build.  On success it bakes the stream (FUN_00406f3c).
//   GaugeAlarmManager::BuildAlarmsForModel @00448d00
//     - for each baked alarm record it makes a GaugeAlarm (FUN_004489e8,
//       0x28 bytes; vtable PTR_FUN_004eed7c; ctor stores entity@+0xc,
//       subsystem@+0x10, condition@+0x14), adds it to the manager's alarm list
//       (this+4, list-insert vtbl+4), then calls the virtual
//         this->ReadGaugeAlarmStreamItem(alarm, entity, subsystem, condition,
//                                         stream)
//       once per record to configure it.
//
// Engine-internal helper map (from the base + the BattleTech alarm bricks):
//      FUN_004489e8 GaugeAlarm ctor            FUN_00448a28 GaugeAlarm dtor
//      FUN_00448ebd GaugeAlarmManager base ctor (chains a ChainOf<GaugeAlarm*>)
//      FUN_0040385c Verify(msg,file,line)
//      FUN_004dbb24 DebugStream << (char*)     FUN_004db78c DebugStream << (int)
//      DAT_00524e20 DebugStream (warning channel)
//      MemoryStream write/read = (*stream + 0x20)(stream,&v,4) / (*stream+0x1c)(...)
//

#include <bt.hpp>
#pragma hdrstop

#if !defined(BTL4GALM_HPP)
#	include <btl4galm.hpp>
#endif
#if !defined(APP_HPP)
#	include <app.hpp>
#endif


//
// Recognised cockpit gauge-alarm type names.  (BattleTech's l4gauge.cfg
// "gaugeAlarm" sections name one of these; the threshold / flash parameters
// follow in alarm_data.)  The exact spelling list could not be recovered from
// this image -- it lived in the folded-away override -- so the set below is the
// minimal set implied by the GaugeAlarm fields the cockpit gauges flash on
// (heat / power / armour / ammo).  BEST-EFFORT.
//
enum GaugeAlarmType
{
	gaugeAlarmThreshold,	// value crosses a fixed threshold
	gaugeAlarmRange,		// value leaves a [low,high] band
	gaugeAlarmState,		// subsystem operational-state change
	gaugeAlarmFlash,		// timed flash while condition holds
	gaugeAlarmTypeCount,
	gaugeAlarmUndefined = -1
};


//
// BTL4GaugeAlarmManager::CreateGaugeAlarmStreamItem
//
// Called by GaugeAlarmManager::CreateGaugeAlarmStream (@00448af0) once per
// "gaugeAlarm" entry while a gauge model is being compiled.  Recognise the
// alarm type spelled in <alarm_name>, parse its parameters out of <alarm_data>,
// and serialise (type, parameters) into <mem_stream>.  Returning False makes
// the base print "Model file '...' has undefined alarm type '<alarm_name>' -
// resource not built." and abandon the model -- so an unknown name MUST yield
// False (that diagnostic is the observable contract).
//
// BEST-EFFORT reconstruction (no distinct override body survived in BTL4OPT.EXE).
//
Logical
	BTL4GaugeAlarmManager::CreateGaugeAlarmStreamItem(
		MemoryStream	*mem_stream,
		const char		*alarm_name,
		const char		*alarm_data
	)
{
	GaugeAlarmType type = gaugeAlarmUndefined;

	//
	// Map the type name -> enum.  (Names best-effort; see note above.)
	//
	if (stricmp(alarm_name, "threshold") == 0)	type = gaugeAlarmThreshold;
	else if (stricmp(alarm_name, "range") == 0)	type = gaugeAlarmRange;
	else if (stricmp(alarm_name, "state") == 0)	type = gaugeAlarmState;
	else if (stricmp(alarm_name, "flash") == 0)	type = gaugeAlarmFlash;

	if (type == gaugeAlarmUndefined)
	{
		//
		// Unknown alarm type: tell the caller so it emits the
		// "undefined alarm type ... resource not built" warning.
		//
		return False;
	}

	//
	// Serialise the type tag followed by the type-specific parameters parsed
	// from the alarm_data text (thresholds, flash period, target colour, ...).
	//
	mem_stream->WriteBytes(&type, sizeof(type));	// (*mem_stream+0x20)(...,4)
	// ... write parsed numeric parameters from alarm_data ...

	return True;
}


//
// BTL4GaugeAlarmManager::ReadGaugeAlarmStreamItem
//
// Called by GaugeAlarmManager::BuildAlarmsForModel (@00448d00) once per baked
// alarm record, with a freshly-constructed GaugeAlarm (already carrying
// the_entity/the_subsystem/the_condition from the GaugeAlarm ctor @004489e8).
// Read the (type, parameters) back out of <mem_stream> and configure <alarm>
// so that, every frame, it samples the named subsystem attribute and raises /
// clears its flashing state when the recorded condition is met.
//
// BEST-EFFORT reconstruction (no distinct override body survived in BTL4OPT.EXE).
//
void
	BTL4GaugeAlarmManager::ReadGaugeAlarmStreamItem(
		GaugeAlarm		*alarm,
		Entity			*the_entity,
		Subsystem		*the_subsystem,
		Enumeration		the_condition,
		MemoryStream	*mem_stream
	)
{
	GaugeAlarmType type;
	mem_stream->ReadBytes(&type, sizeof(type));	// (*mem_stream+0x1c)(...,4)

	//
	// Bind the alarm to its data source and trip parameters.  The base
	// GaugeAlarm already stores entity/subsystem/condition; here we attach the
	// type-specific trip (threshold / band / state / flash period) read from
	// the stream so GaugeAlarm::Execute can flash the owning gauge.
	//
	switch (type)
	{
	case gaugeAlarmThreshold:
		// alarm->SetThreshold( read Scalar );  alarm->SetCondition(the_condition);
		break;
	case gaugeAlarmRange:
		// alarm->SetBand( read low, read high );
		break;
	case gaugeAlarmState:
		// alarm->WatchState(the_subsystem);
		break;
	case gaugeAlarmFlash:
		// alarm->SetFlashPeriod( read Scalar );
		break;
	default:
		Verify(False, "Bad gauge alarm type",
			"d:\\tesla\\bt\\bt_l4\\BTL4GALM.CPP", 0);
		break;
	}

	(void)the_entity;
	(void)the_subsystem;
	(void)the_condition;
}
