// EdGameObject.cpp: implementation of the EdGameObject class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MW4GameEd2.h"
#include "EdGameObject.h"
#include "GameInterface.h"
#include "GameObjPropPanal.h"
#include "ObjPanelDlg.h"
#include "ObjProps.h"
#include "ObjManListCtrl.h"
#include "NameManager.h"
#include "drawInfo.h"
//#include <Adept\Adept.hpp>
#include <Adept\Entity.hpp>
#include <Adept\Zone.hpp>
#include <Adept\Map.hpp>
#include <MW4\MW4.hpp>
#include <MW4\Vehicle.hpp>
#include <MW4\Building.hpp>
#include <MW4\NonCom.hpp>
#include <MW4\Turret.hpp>
#include <MW4\Airplane.hpp>
#include <MW4\Flag.hpp>
#include <MW4\Team.hpp>
#include <MW4\Navpoint.hpp>
#include <MW4\Cultural.hpp>
#include <Adept\Dropzone.hpp>
#include <Adept\CollisionVolume.hpp>
#include <MW4\MWTool.hpp>
#include <MW4\Mech_AI.hpp>
#include <MW4\PlaneAI.hpp>
#include <MW4\ShooterAI.hpp>
#include <MW4\NonComAI.hpp>
#include <MW4\Mech.hpp>
#include <MW4\WaterCultural.hpp>
#include <MW4\MFB.hpp>
#include <Adept\EntityManager.hpp>
#include <MW4\aiutils.hpp>
using namespace MW4AI;
using namespace Adept;
using namespace MechWarrior4;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


EdGameObject::EdGameObject():EdGUIObject()
{
	MyEntity = NULL;
	InMap=false;
	SnapToGround=false;
	Alignment=Entity::DefaultAlignment;
	Skin='_';
	AIType="<NONE>";
	m_ScriptName="";
	for(int i=0;i<DEFAULT_MEMORYCELL_VALUES;i++) MemoryCell[i]=0.0f;
	DrawFromOBB=false;
	UseGameCollsion=true;
	Changeable=true;
}

void EdGameObject::AssociateTo(Adept::Entity *entity)
{
	
	InMap=false;
	
	
	// Alterted for performance
	//	EdGUIObject::SetMat(entity->GetLocalToParent());
	LinearMatrix4D mat=entity->GetLocalToParent();
	SetMatNoUpdate(mat);
	Point3D pnt;
	pnt=mat;
	HoverElevation=pnt.y-ComputeTerrainElevation(pnt.x,pnt.z,entity);
	SnapToGround=true;
	
	
	if(entity->GetParentEntity()==Map::GetInstance())
	{
		InMap=true;
	}
	
	MyEntity=entity;
	
	ResourcePath=MyEntity->GetGameModelResourceName();
	ResourcePath=ResourcePath.Left(ResourcePath.Find(".data"));
	ResourcePath+=".Instance";

	//	SetName(CString((char *)entity->instanceName));
	//	For Performance Assume the name is unique
	Name=CString((char *)entity->instanceName);
	
	
	if(Name=="") 
	{
	CString base_name=ResourcePath;
	base_name=base_name.Left(base_name.ReverseFind('.'));
	base_name=base_name.Mid(base_name.ReverseFind('\\')+1);
	SetName(base_name);
	}
	else
	NameManager::Instance->AddString(Name);
	
	

	Alignment=MyEntity->GetAlignment();
	
	Skin=GetEntitySkin(MyEntity);
	
	//Sync AI
	if (MyEntity->IsDerivedFrom(MWObject::DefaultData))
	{
		MechWarrior4::MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
		Check_Object(mwobject);
		MechWarrior4::AI* ai = mwobject->GetAI();
		if (ai == 0)
			AIType="<NONE>";
		else
		{
			if(ai->IsDerivedFrom(MechWarrior4::PlaneAI::DefaultData)) AIType="PlaneAI";
			else if(ai->IsDerivedFrom(MechWarrior4::MechAI::DefaultData)) AIType="MechAI";
			else if(ai->IsDerivedFrom(MechWarrior4::ShooterAI::DefaultData)) AIType="ShooterAI";
			else if(ai->IsDerivedFrom(MechWarrior4::NonComAI::DefaultData)) AIType="NonComAI";
			else if(ai->IsDerivedFrom(MechWarrior4::CombatAI::DefaultData)) AIType="CombatAI";
			else if(ai->IsDerivedFrom(MechWarrior4::MoverAI::DefaultData)) AIType="MoverAI";
			else if(ai->IsDerivedFrom(MechWarrior4::AI::DefaultData)) AIType="AI";
		}
	}
	else
		AIType="<NONE>";
	
	
	
	//Sync up Cells
	if ((MyEntity->IsDerivedFrom(MWObject::DefaultData) == true))
	{
		MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
		if (mwobject->GetAI() != 0)
		{
			for(int i=0;i<DEFAULT_MEMORYCELL_VALUES;i++) MemoryCell[i]=mwobject->GetAI()->RealMemory(i);
		}
	}
	
	m_ScriptName=GetEntityScriptName(MyEntity);
	Check_Object(MyEntity);
	if(InMap)
	{
		BuildDisplayInfoFromData();
	}
	else
	{
		AddToMap();
		BuildDisplayInfoFromData();
		RemoveFromMap();
	}

	SetAlignment(Alignment);

PickPen();
}	

bool EdGameObject::InRadius( Point3D &pnt)
{
return EdGUIObject::InRadius(pnt);
/*
// The following is for Object percise selection which was deemed troublesome do to underselction problems.
  
	if(EdGUIObject::InRadius(pnt))
	{
		if(UseGameCollsion && MyEntity && (MyEntity->CanBeShot() || MyEntity->CanBeWalkedOn()) && Visual)
		{
			float height;
			Entity* top_entity = GetTopEntity(pnt.x,pnt.z,height);
			if(MyEntity == top_entity)
			{
				return true;
			}
			else
			{
				if (top_entity == Adept::Map::GetInstance())
				{
					Stuff::Point3D my_height(MyEntity->GetLocalToWorld());
					
					if (my_height.y < (height - 2.0f))
					{
						return (true);
					}	
				}
			}
		}
		else
		{
			return true;
		}
	}
	return false;
*/
 }

void EdGameObject::ChangeTo(CString &path)
{
	AIType="<None>";
	m_ScriptName="";
	BuildFrom(path,GetName());
}

void EdGameObject::BuildFrom(CString &res_name,CString &name)
{
	if(MyEntity) Clear();
	
	ResourcePath=res_name;
	EdGUIObject::SetName(name);
	Adept::Resource res((LPCSTR)ResourcePath);
	res.LoadData();
	Check_Object(Connection::Local);
	ReplicatorID base_id = Connection::Local->GetNextReplicatorID();
	MyEntity = Entity::CreateEntity(&res,&base_id);
	Check_Object(MyEntity);
	
	Check_Object(EntityManager::GetInstance());

	//TOM CHECK THIS
//	if(MyEntity->instanceName && EntityManager::GetInstance()->GetMover(MyEntity->instanceName))
	//if(MyEntity->instanceName)
//	{
	//	Verify(MyEntity->IsDerivedFrom(Mover::DefaultData));
	//	Mover *mover = Cast_Object(Mover *, MyEntity);
	//	EntityManager::GetInstance()->RemoveMover(mover);
	//	MyEntity->instanceName=(char *)(LPCSTR)GetName();
	//	EntityManager::GetInstance()->AddMover(mover);
//	}
//	else
//	{
		MyEntity->instanceName=(char *)(LPCSTR)GetName();
//	}
	
	MyEntity->SetPropType(Entity::MissionPropType);
	
	SetAlignment(Alignment);
	SetSkin(Skin);
	SetAIType(AIType);
	SetScriptName(m_ScriptName);
	
	for(int i=0;i<DEFAULT_MEMORYCELL_VALUES;i++) SetMemoryCell(i,MemoryCell[i]);
	
	PickPen();
	AddToMap();
	BuildDisplayInfoFromData();
	
}

bool EdGameObject::IsMultiZone()
{
	
	if(MyEntity!=NULL && MyEntity->IsMultiZone() )  return true;
	return false;
}

bool EdGameObject::IsMultiTile()		
{
	if(MyEntity!=NULL && MyEntity->IsMultiTile() )  return true;
	return false;
}

void EdGameObject::SelectMultiZone()	
{
	if(MyEntity!=NULL && MyEntity->IsMultiZone() )  
		Select();
}

void EdGameObject::SelectMultiTile()	
{
	if(MyEntity!=NULL && MyEntity->IsMultiTile() )  
		Select();
}

void EdGameObject::PickPen()
{
	Check_Object(MyEntity);
	if(MyEntity->IsDerivedFrom(Mech::DefaultData))
		DrawPen=DrawInfo::MechPen;
	else
		if(MyEntity->IsDerivedFrom(Vehicle::DefaultData))
			DrawPen=DrawInfo::VehiclePen;
		else
			if(MyEntity->IsDerivedFrom(Building::DefaultData) )
				DrawPen=DrawInfo::BuildingPen;
			else
				if(MyEntity->IsDerivedFrom(Cultural::DefaultData) )
					DrawPen=DrawInfo::CulturalPen;
				else		
				if(MyEntity->IsDerivedFrom(NonCom::DefaultData) )
					DrawPen=DrawInfo::NonComPen;
					else
					DrawPen=DrawInfo::HelperPen;
}

void EdGameObject::BuildDisplayInfoFromData()
{
Check_Object(MyEntity);
	if ( MyEntity->IsDerivedFrom(MechWarrior4::NonCom::DefaultData) )    UseGameCollsion=false;

	if(!IsVisual()) return;
		DrawFromOBB=false;
	
	if(MyEntity->GetSolidVolume()!=NULL)
	{
		if(LineCount!=0)
		{
			Verify(LineCount>0);
			if(LineList) delete LineList;
			LineList=NULL;
			LineCount=0;
		}
		DrawFromOBB=true;

	}
	else
	{
		Scalar rad=MyEntity->GetElement()->m_localOBB.sphereRadius;
	
		
		if(LineCount!=12)
		{
			LineCount=12;
			if(LineList) delete LineList;
			LineList=new GUILine[LineCount];
		}
		
		LineList[0].SetLine(Point3D(-rad,-rad,-rad),
			Point3D(rad,-rad,-rad));
		LineList[1].SetLine(Point3D(rad,-rad,-rad),
			Point3D(rad,-rad,rad));
		LineList[2].SetLine(Point3D(rad,-rad,rad),
			Point3D(-rad,-rad,rad));
		LineList[3].SetLine(Point3D(-rad,-rad,rad),
			Point3D(-rad,-rad,-rad));
		
		LineList[4].SetLine(Point3D(-rad,rad,-rad),
			Point3D(rad,rad,-rad));
		LineList[5].SetLine(Point3D(rad,rad,-rad),
			Point3D(rad,rad,rad));
		LineList[6].SetLine(Point3D(rad,rad,rad),
			Point3D(-rad,rad,rad));
		LineList[7].SetLine(Point3D(-rad,rad,rad),
			Point3D(-rad,rad,-rad));
		
		LineList[8].SetLine(Point3D(-rad,-rad,-rad),
			Point3D(-rad,rad,-rad));
		LineList[9].SetLine(Point3D(rad,-rad,rad),
			Point3D(rad,rad,rad));
		LineList[10].SetLine(Point3D(-rad,-rad,rad),
			Point3D(-rad,rad,rad));
		LineList[11].SetLine(Point3D(rad,-rad,-rad),
			Point3D(rad,rad,-rad));
	}
	
	if(MyEntity->IsDerivedFrom(WaterCultural::DefaultData))
	{
		ScreenDiv=75;
		RadiusSqu=0;
		Visual=false;
	}
	else
		BuildRadius();
	
	
}

void EdGameObject::BuildRadius()
{
	if(DrawFromOBB)
	{
		Verify(MyEntity && InMap && MyEntity->GetSolidVolume()); 
		const OBB &obbTmp=MyEntity->GetSolidVolume()->m_localSpaceBounds;
		RadiusSqu=obbTmp.sphereRadius*obbTmp.sphereRadius;
	}
	else
	{
		EdGUIObject::BuildRadius();
	}
	
}


void EdGameObject::SetName( CString &name)
{
	EdGUIObject::SetName(name);
	if(InMap)
		SetEntityName(MyEntity,GetName());
}



void EdGameObject::RemoveFromMap()
{
	if(MyEntity && InMap)
	{
		RemoveEntityFromMap(MyEntity);		
		InMap=false;
	}
	
	//	EdGUIObject::RemoveFromMap();
}

void EdGameObject::AddToMap()
{
	if(MyEntity && !InMap)
	{
		AddEntityToMap(MyEntity,GetMat());
		InMap=true;
	}
	
	//	EdGUIObject::AddToMap();
}

void EdGameObject::UpdateMat()
{
	RemoveFromMap();
	EdGUIObject::UpdateMat();
	AddToMap();
}

void EdGameObject::Clear()
{
	if(MyEntity!=NULL)
	{
		Check_Object(MyEntity);
		if(InMap)
		{
			RemoveFromMap();
		}
		delete Cast_Object(Stuff::Plug *,MyEntity);
		
	}
}

EdGameObject::~EdGameObject()
{
	Clear();
}

void EdGameObject::SetAlignment(int align)
{
	Alignment=align;
	if(MyEntity!=NULL)
	{
		Verify(align<Entity::LastAlignment);
		MyEntity->SetAlignment(Alignment);
		if(MyEntity->IsDerivedFrom(Vehicle::DefaultData) && !MyEntity->IsDerivedFrom(Mech::DefaultData))
			if(Alignment==Entity::Enemy) SetSkin('_'); else SetSkin('0');
	}
}

int EdGameObject::GetAlignment()	
{
	return Alignment;
}

CString EdGameObject::GetAIType()
{
	return AIType;
}

void EdGameObject::FillValidAITypes(CComboBox *con)
{
	if ((MyEntity == 0) ||
		(MyEntity->IsDerivedFrom(MWObject::DefaultData) == false))
	{
		return;
	}
	MechWarrior4::MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
	Check_Object(mwobject);
	
	if (mwobject->IsDerivedFrom(MWObject::DefaultData)) con->AddString("AI");
	if (mwobject->IsDerivedFrom(Vehicle::DefaultData))	con->AddString("MoverAI");
	if (mwobject->IsDerivedFrom(Vehicle::DefaultData))	con->AddString("CombatAI");
	if (mwobject->IsDerivedFrom(MWObject::DefaultData)) con->AddString("ShooterAI");
	if (mwobject->IsDerivedFrom(NonCom::DefaultData))	con->AddString("NonComAI");
	if (mwobject->IsDerivedFrom(Mech::DefaultData))		con->AddString("MechAI");
	if (mwobject->IsDerivedFrom(Airplane::DefaultData)) con->AddString("PlaneAI");
}

CString EdGameObject::GetBestAIType() const
{
	if ((MyEntity == 0) ||
		(MyEntity->IsDerivedFrom(MWObject::DefaultData) == false))
	{
		return ("<NONE>");
	}
	
	MechWarrior4::MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
	Check_Object(mwobject);
	
	if (mwobject->IsDerivedFrom(MechWarrior4::Vehicle::DefaultData) == false)
	{
		if (mwobject->IsDerivedFrom(MechWarrior4::NonCom::DefaultData) == true)
		{
			return ("NonComAI");
		}
		
		if (mwobject->weaponChain.GetSize() == 0)
		{
			return ("AI");
		}
		
		return ("ShooterAI");
	}
	
	if (mwobject->IsDerivedFrom(Mech::DefaultData) == true)
	{
		return ("MechAI");
	}
	
	if (mwobject->IsDerivedFrom(Airplane::DefaultData) == true)
	{
		return ("PlaneAI");
	}
	
	if (mwobject->weaponChain.GetSize() == 0)
	{
		return ("MoverAI");
	}
	
	return ("CombatAI");
}

void EdGameObject::SetDefaultAI()
{
	SetAIType(GetBestAIType());
}


template <class create_message_type>
void CreateAndAttachAI(MechWarrior4::MWObject& mwobject, const CString& type_name, Adept::Entity::ClassData* class_data)
{
	UnBindEntity(&mwobject);
	CString resource_name("Content\\AIPlayers\\");
	resource_name += type_name;
	resource_name += "\\";
	resource_name += type_name;
	resource_name += ".data";
	
	Adept::Resource r(resource_name);
	r.LoadData();
	
	Stuff::Scalar blank_cells[DEFAULT_MEMORYCELL_VALUES];
	for (int i=0;i<DEFAULT_MEMORYCELL_VALUES;++i) blank_cells[i]=0;
	
	create_message_type create_message(sizeof(create_message_type),
		DefaultEventPriority,
		create_message_type::DefaultFlags,
		class_data->GetClassID(),
		create_message_type::DefaultFlags,
		r.GetResourceID(),
		mwobject.GetLocalToWorld(),
		0.0f,
		Entity__ExecutionStateEngine::AlwaysExecuteState,
		NameTable::NullObjectID,
		mwobject.GetAlignment(),
		DropZone::Null,
		//			 NameTable::NullObjectID,
		mwobject.objectID,
		"",		// script name,  should be scripts\<filename>.abl
		blank_cells,		// memory cell data
		-1, // pilotSkill
		-1, // gunnerySkill
		-1, // eliteSkill
		-1, // minHeatSkill
		-1, // maxHeatSkill
		-1, // sensor
		-1, // blind
		-1, // longrange
		-1, // shortrange
		0,
		0,
		0);
	
	MemoryStream stream(&create_message,create_message.messageLength);
	
	ReplicatorID ai_id = Connection::Local->GetNextReplicatorID();
	Adept::Entity* ai_entity = Entity::CreateEntity(&stream,&ai_id,false);
	
	Check_Object(ai_entity);
	Verify(ai_entity->IsDerivedFrom(class_data));
	
	ai_entity->instanceName = type_name;
	ai_entity->instanceName += "_";
	ai_entity->instanceName += mwobject.instanceName;
	ai_entity->instanceName += "_";
	ai_entity->instanceName += IntToString(rand() % 1000).c_str();
	
	AI* ai = Cast_Object(AI*,ai_entity);
	
	ai->ConnectEntity(&mwobject);
	mwobject.AttachAI(ai);
}

void EdGameObject::SetAIType(const CString& type)
{
	
	AIType=type;
	
	if ((MyEntity == 0) ||
		(MyEntity->IsDerivedFrom(MWObject::DefaultData) == false))
	{
		return;
	}
	
	MechWarrior4::MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
	Check_Object(mwobject);
	
	if (AIType == "<NONE>")
	{
		mwobject->AttachAI(0);
		return;
	}
	
#define CREATE_AND_ATTACH(type_name)	\
	if (AIType == #type_name)			\
	{									\
	RemoveEntityAI(MyEntity);		\
	CreateAndAttachAI<##type_name::CreateMessage>(*mwobject,#type_name,##type_name::DefaultData);	\
	AddEntityAI(MyEntity);			\
	return;							\
	}
	
	CREATE_AND_ATTACH(MechAI);
	CREATE_AND_ATTACH(PlaneAI);
	CREATE_AND_ATTACH(NonComAI);
	CREATE_AND_ATTACH(ShooterAI);
	CREATE_AND_ATTACH(CombatAI);
	CREATE_AND_ATTACH(MoverAI);
	CREATE_AND_ATTACH(AI);
	
#undef CREATE_AND_ATTACH
}

void EdGameObject::MakeVisible(DWORD *visflag)
{
	if (MyEntity == 0) 	return; 
	if (MyEntity->IsDerivedFrom(WaterCultural::DefaultData) )			 {*visflag|=SHOW_WATER; return; }
	if ( MyEntity->IsDerivedFrom(MechWarrior4::Mech::DefaultData) )      {*visflag|=SHOW_MECHS;     return;}
	if ( MyEntity->IsDerivedFrom(MechWarrior4::Airplane::DefaultData))   {*visflag|=SHOW_AIRPLANES; return;}
	if ( MyEntity->IsDerivedFrom(MechWarrior4::NonCom::DefaultData) )    {*visflag|=SHOW_NONCOMS;   return;}
	if ( MyEntity->IsDerivedFrom(MechWarrior4::Building::DefaultData) )  {*visflag|=SHOW_BUILDINGS; return;}
	if ( MyEntity->IsDerivedFrom(Cultural::DefaultData))				 {*visflag|=SHOW_CULTURALS; return;}
	if ( MyEntity->IsDerivedFrom(MechWarrior4::NavPoint::DefaultData))			 {*visflag|=SHOW_NAVPOINTS; return;}
	if ( MyEntity->IsDerivedFrom(Flag::DefaultData))			 {*visflag|=SHOW_FLAGS; return;}
	if ( MyEntity->IsDerivedFrom(Team::DefaultData))			 {*visflag|=SHOW_TEAMS; return;}
	if ( MyEntity->IsDerivedFrom(MechWarrior4::Vehicle::DefaultData))	 {*visflag|=SHOW_VEHICLES; return;}
	
}


void EdGameObject::UpdateVisibility(DWORD visflags)
{
	if (MyEntity == 0) 
	{
		SetHide(false);
		return; 
	}
	
	if ((visflags&SHOW_FRIENDLY && MyEntity->GetAlignment()==Entity::Player ) ||
		(visflags&SHOW_NEUTRAL  && MyEntity->GetAlignment()==Entity::DefaultAlignment ) ||
		(visflags&SHOW_ENEMY    && MyEntity->GetAlignment()==Entity::Enemy ))
	{
		SetHide(false);
		return;
	}
	
	if (visflags&SHOW_WATER && MyEntity->IsDerivedFrom(WaterCultural::DefaultData) )
	{
		SetHide(false);
		return;
	}
	
	if ((visflags&SHOW_MECHS && MyEntity->IsDerivedFrom(MechWarrior4::Mech::DefaultData) ) ||
		(visflags&SHOW_AIRPLANES && MyEntity->IsDerivedFrom(MechWarrior4::Airplane::DefaultData)) ||
		(visflags&SHOW_NONCOMS && MyEntity->IsDerivedFrom(MechWarrior4::NonCom::DefaultData) ) ||
		(visflags&SHOW_BUILDINGS && MyEntity->IsDerivedFrom(MechWarrior4::Building::DefaultData) ) ||
		(visflags&SHOW_CULTURALS && MyEntity->IsDerivedFrom(Cultural::DefaultData) && !MyEntity->IsDerivedFrom(WaterCultural::DefaultData) ) ||
		(visflags&SHOW_NAVPOINTS && MyEntity->IsDerivedFrom(MechWarrior4::NavPoint::DefaultData) ) ||
		(visflags&SHOW_FLAGS && MyEntity->IsDerivedFrom(Flag::DefaultData) ) ||
		(visflags&SHOW_TEAMS && MyEntity->IsDerivedFrom(Team::DefaultData) )
		)
	{
		SetHide(false);
		return;
	}
	
	if (visflags&SHOW_VEHICLES)
	{
		if ((MyEntity->IsDerivedFrom(MechWarrior4::Vehicle::DefaultData)  || MyEntity->IsDerivedFrom(MechWarrior4::MFB::DefaultData)) &&
			(MyEntity->IsDerivedFrom(MechWarrior4::Mech::DefaultData) == false) &&
			(MyEntity->IsDerivedFrom(MechWarrior4::Airplane::DefaultData) == false) 
			)
		{
			SetHide(false);
			return;
		}
	}
	
	CString ai_type(GetAIType());
	
	if ((visflags&SHOW_AI_NONE && !ai_type.CompareNoCase("<NONE>") ) ||
		(visflags&SHOW_AI && !ai_type.CompareNoCase("AI")		 ) ||
		(visflags&SHOW_MOVERAI && !ai_type.CompareNoCase("MoverAI")   ) ||
		(visflags&SHOW_COMBATAI && !ai_type.CompareNoCase("CombatAI") ) ||
		(visflags&SHOW_NONCOMAI && !ai_type.CompareNoCase("NonComAI")  ) ||
		(visflags&SHOW_SHOOTERAI && !ai_type.CompareNoCase("ShooterAI") ) ||
		(visflags&SHOW_MECHAI && !ai_type.CompareNoCase("MechAI")	 ) ||
		(visflags&SHOW_PLANEAI && !ai_type.CompareNoCase("PlaneAI")	 ))
	{
		SetHide(false);
		return;
	}
	
	if (!(MyEntity->IsDerivedFrom(MechWarrior4::Mech::DefaultData)  ||
		MyEntity->IsDerivedFrom(MechWarrior4::Airplane::DefaultData) ||
		MyEntity->IsDerivedFrom(MechWarrior4::NonCom::DefaultData)  ||
		MyEntity->IsDerivedFrom(MechWarrior4::Vehicle::DefaultData)  ||
		MyEntity->IsDerivedFrom(MechWarrior4::Building::DefaultData)  ||
		MyEntity->IsDerivedFrom(MechWarrior4::Cultural::DefaultData)  ||
		MyEntity->IsDerivedFrom(MechWarrior4::NavPoint::DefaultData)  ||
		MyEntity->IsDerivedFrom(Flag::DefaultData)  ||
		MyEntity->IsDerivedFrom(Team::DefaultData) )  
		)
	{
		SetHide(false);
		return;
	}
	
	SetHide(true);
}

void EdGameObject::AddPanel(CObjPanelDlg *pnl,UndoCommand **cmd)
{
	EdGUIObject::AddPanel(pnl,cmd);
	pnl->AddPanel((CPanelDlg *)new CGameObjPropPanal(this,cmd,pnl));
	
	
}

CString EdGameObject::GetTag(unsigned long tag_flags)
{
	CString ftag(EdGUIObject::GetTag(tag_flags));
	
	if (MyEntity != 0)
	{
		if (tag_flags&TAG_TYPE)
		{
			ftag+=GetTypeName() + ": " + GetResourceName()+"\n";
		}
		
		if (tag_flags&TAG_ALIGNMENT)
		{
			ftag+=(char *)Entity::AlignmentAsciiToText(GetAlignment());
			ftag+="\n";
		}
		
		if (MyEntity->IsDerivedFrom(MWObject::DefaultData) == true)
		{
			MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
			
			if ((tag_flags & TAG_AINAME) > 0)
			{
				if (mwobject->GetAI() != 0)
				{
					ftag += "AI: ";
					ftag += mwobject->GetAI()->instanceName;
					ftag += "\n";
				}
				else
				{
					ftag += "No AI\n";
				}
			}
			
			if ((tag_flags & TAG_AITYPE) > 0)
			{
				ftag += "AI Type: ";
				ftag += GetAIType();
				ftag += "\n";
			}
			
			if ((tag_flags & TAG_SCRIPT) > 0)
			{
				if ((mwobject->GetAI() != 0) &&
					(mwobject->GetAI()->GetScriptName() != 0))
				{
					CString scriptname;
					scriptname=mwobject->GetAI()->GetScriptName();
					int pos=scriptname.ReverseFind('\\');
					if(pos>=0) scriptname=scriptname.Mid(pos+1);

					ftag += "Script: ";
					ftag += scriptname;
					ftag += "\n";
				}
				else
				{
					ftag += "No Script\n";
				}
			}
		}
		
		if ((tag_flags & TAG_SKINTYPE) > 0)
		{
			ftag += "Skin: ";
			ftag += GetSkinText();
			ftag += "\n";
		}
	}
	
	return ftag;
}




void EdGameObject::SetSkin(char id)
{
	Skin=id;
	if(MyEntity && HasSkin(MyEntity))
		SetEntitySkin(MyEntity,Skin);
}

CString EdGameObject::GetScriptName()
{
	return m_ScriptName;
}

void EdGameObject::SetScriptName(CString script_name)
{
	m_ScriptName=script_name;
	if(MyEntity)
		SetEntityScriptName(MyEntity,(char *)(LPCSTR)script_name);
}

bool EdGameObject::HasAI() const
{
	if ((MyEntity != 0) &&
		(MyEntity->IsDerivedFrom(MWObject::DefaultData) == true))
	{
		MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
		
		return (mwobject->GetAI() != 0);
	}
	
	return (false);
}

void EdGameObject::SetMemoryCell(int cell, Scalar value)
{
	Verify(cell<DEFAULT_MEMORYCELL_VALUES);
	MemoryCell[cell]=value;
	if ((MyEntity != 0) &&
		(MyEntity->IsDerivedFrom(MWObject::DefaultData) == true))
	{
		MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
		
		if (mwobject->GetAI() != 0)
		{
			mwobject->GetAI()->RealMemory(cell,value);
		}
	}
}

Scalar EdGameObject::GetMemoryCell(int cell) const
{
	Verify(cell<DEFAULT_MEMORYCELL_VALUES);
	return MemoryCell[cell];
	
}

void EdGameObject::Copy(EdGameObject &obj)
{
	EdGUIObject::Copy(obj);
	Clear();
	BuildFrom(obj.ResourcePath,GetName());
	SetAIType(obj.GetAIType());
	SetScriptName(obj.GetScriptName());
	SetAlignment(obj.GetAlignment());
	SetSkin(obj.GetSkin());

	for(int i=0;i<DEFAULT_MEMORYCELL_VALUES;i++)
		SetMemoryCell(i,obj.GetMemoryCell(i));
	RemoveFromMap();
	
}

EdGUIObject *EdGameObject::Clone()
{
	EdGameObject *obj=new EdGameObject;
	obj->Copy(*this);
	return obj;
}

CString EdGameObject::GetResourceName()
{
	CString type_name=ResourcePath;
	type_name=type_name.Left(type_name.ReverseFind('.'));
	type_name=type_name.Mid(type_name.ReverseFind('\\')+1);
	return type_name;
}


int EdGameObject::GetUnSelIcon()
{
	if(MyEntity==NULL) return ICON_NONE;
	
	if (MyEntity->IsDerivedFrom(WaterCultural::DefaultData) == true)
		return ICON_WATER;
	else if (MyEntity->IsDerivedFrom(Mech::DefaultData) == true)
		return ICON_MECH;
	else if (MyEntity->IsDerivedFrom(Airplane::DefaultData) == true)
		return ICON_AIRPLANE;
	else if ((MyEntity->IsDerivedFrom(Building::DefaultData) == true) || (MyEntity->IsDerivedFrom(MFB::DefaultData) == true))
		return ICON_BUILDING;
	else if (MyEntity->IsDerivedFrom(Vehicle::DefaultData) == true)
		return ICON_VEHICLE;
	else if (MyEntity->IsDerivedFrom(NonCom::DefaultData) == true)
		return ICON_NONCOM;
	else if (MyEntity->IsDerivedFrom(NavPoint::DefaultData) == true)
		return ICON_NAVPOINT;
	else if (MyEntity->IsDerivedFrom(Cultural::DefaultData) == true)
		return ICON_CULTURAL;
	
	return ICON_NONE;
}

CString EdGameObject::GetTypeName()
{
	if (MyEntity != 0)
	{
		if (MyEntity->IsDerivedFrom(MechWarrior4::Mech::DefaultData) == true)
			return "Mech";
		else if (MyEntity->IsDerivedFrom(MechWarrior4::Airplane::DefaultData) == true)
			return "Airplane";
		else if (MyEntity->IsDerivedFrom(MechWarrior4::NonCom::DefaultData) == true)
			return "NonCom";
		else if (MyEntity->IsDerivedFrom(MechWarrior4::Vehicle::DefaultData) == true)
			return "Vehicle";
		else if (MyEntity->IsDerivedFrom(MechWarrior4::Building::DefaultData) == true)
			return "Building";
		else if (MyEntity->IsDerivedFrom(MechWarrior4::Flag::DefaultData) == true)
			return "Flag";
		else if (MyEntity->IsDerivedFrom(MechWarrior4::NavPoint::DefaultData) == true)
			return "NavPoint";
		else if (MyEntity->IsDerivedFrom(MechWarrior4::MWObject::DefaultData) == true)
			return "Cultural";
	}
	
	return "Game Object";
}

int EdGameObject::AddToList(CObjManListCtrl *list,unsigned long tagflag)
{
	if(IsHidden()) return -1;
	LVITEM lvitm;
	int idx=EdGUIObject::AddToList(list,tagflag);
	
	ZeroMemory(&lvitm,sizeof(lvitm));
	lvitm.mask=LVIF_TEXT;
	lvitm.iItem=idx;
	CString str;
	
	
	if(tagflag&TAG_ALIGNMENT)
	{
		lvitm.iSubItem=list->GetColWithID(TAGI_ALIGNMENT);
		lvitm.pszText=(char *)Entity::AlignmentAsciiToText(GetAlignment());
		list->SetItem(&lvitm);
	}
	
	if(tagflag&TAG_AINAME)
	{
		lvitm.iSubItem=list->GetColWithID(TAGI_AINAME);
		str="None";
		if (MyEntity != 0 && MyEntity->IsDerivedFrom(MWObject::DefaultData))
		{
			MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
			if(mwobject->GetAI())
			{
				str=mwobject->GetAI()->instanceName;
			}
		}
		lvitm.pszText=str.GetBuffer(0);
		list->SetItem(&lvitm);
	}
	
	if(tagflag&TAG_AITYPE)
	{
		lvitm.iSubItem=list->GetColWithID(TAGI_AITYPE);
		str=GetAIType();
		lvitm.pszText=str.GetBuffer(0);
		list->SetItem(&lvitm);
	}
	
	
	if(tagflag&TAG_SKINTYPE)
	{
		lvitm.iSubItem=list->GetColWithID(TAGI_SKINTYPE);
		str=GetSkinText();
		lvitm.pszText=str.GetBuffer(0);
		list->SetItem(&lvitm);
	}
	
	
	if(tagflag&TAG_SCRIPT)
	{
		lvitm.iSubItem=list->GetColWithID(TAGI_SCRIPT);
		str="None";
		if (MyEntity != 0 && MyEntity->IsDerivedFrom(MWObject::DefaultData))
		{
			MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
			if ((mwobject->GetAI() != 0) &&
				(mwobject->GetAI()->GetScriptName() != 0))
			{
				int pos;
				str=mwobject->GetAI()->GetScriptName();
				pos=str.ReverseFind('\\');
				if(pos>0) str=str.Mid(pos+1);

			}
		}
		lvitm.pszText=str.GetBuffer(0);
		list->SetItem(&lvitm);
	}
	
	
	return idx;
}

void EdGameObject::DrawTileViolation(DrawInfo &dinf)
{
if(!IsMultiTile()) return;
dinf.SetPen(DrawInfo::WarningPen);
	Point3D start,end;
	CPoint p1,p2;

if(MyEntity->GetMinTileRow() != MyEntity->GetMaxTileRow())
	{
	start.y=end.y=0.0f;
	start.z=end.z=MyEntity->GetMaxTileRow()*Adept::c_TileSize-dinf.vinf.GetMapSize().x*0.5f;
	start.x=MyEntity->GetMaxTileCol()*Adept::c_TileSize-dinf.vinf.GetMapSize().z*0.5f;
	end.x=start.x+c_TileSize;
	p1=dinf.vinf.DataToScreen(start);
	p2=dinf.vinf.DataToScreen(end);
	dinf.GetDC()->MoveTo(p1);
	dinf.GetDC()->LineTo(p2);
	}

if(MyEntity->GetMinTileCol() != MyEntity->GetMaxTileCol())
	{
	start.y=end.y=0.0f;
	start.x=end.x=MyEntity->GetMaxTileCol()*c_TileSize-dinf.vinf.GetMapSize().z*0.5f;
	start.z=MyEntity->GetMaxTileRow()*c_TileSize-dinf.vinf.GetMapSize().x*0.5f;
	end.z=start.z+c_TileSize;
	p1=dinf.vinf.DataToScreen(start);
	p2=dinf.vinf.DataToScreen(end);
	dinf.GetDC()->MoveTo(p1);
	dinf.GetDC()->LineTo(p2);
	}


}


void EdGameObject::Draw(DrawInfo &dinf)
{
	if(IsHidden() || !InDisplayRegion(dinf)) return;
	
			SetPen(dinf);
	
	if(DrawFromOBB)
	{
		Verify(MyEntity && InMap);
		Verify(MyEntity->GetSolidVolume()!=NULL);
		Point3D center=GetPos();
		const OBB &obbTmp=MyEntity->GetSolidVolume()->m_localSpaceBounds;
		Verify(obbTmp.axisExtents.x!=0.0f && obbTmp.axisExtents.z!=0.0f);
		
		LinearMatrix4D mat,mat1,mat2;
		mat1=MyEntity->GetLocalToWorld();
		mat2=obbTmp.localToParent;
		mat.Multiply(mat2,mat1);
		mat.Normalize();
		YawPitchRoll ypr;
		ypr=mat;
		
		if(Small_Enough(ypr.pitch) &&  Small_Enough(ypr.roll))
		{	// This is not really a box just a square from this view
		if(Close_Enough(ypr.yaw,0.0f) || Close_Enough(ypr.yaw,Pi))	//Special ops for regular squares
		{
		Point3D tl,br;
		CPoint p1,p2;
		tl.x=center.x-obbTmp.axisExtents.x;
		tl.z=center.z-obbTmp.axisExtents.z;
		br.x=center.x+obbTmp.axisExtents.x;
		br.z=center.z+obbTmp.axisExtents.z;
		p1=dinf.vinf.DataToScreen(tl);
		p2=dinf.vinf.DataToScreen(br);
		dinf.GetDC()->Rectangle(p1.x,p1.y,p2.x,p2.y);
		}
		else if(Close_Enough(ypr.yaw,Pi_Over_2) || Close_Enough(ypr.yaw,Two_Pi/3.0f))
		{
		Point3D tl,br;
		CPoint p1,p2;
		tl.z=center.z-obbTmp.axisExtents.x;
		tl.x=center.x-obbTmp.axisExtents.z;
		br.z=center.z+obbTmp.axisExtents.x;
		br.x=center.x+obbTmp.axisExtents.z;
		p1=dinf.vinf.DataToScreen(tl);
		p2=dinf.vinf.DataToScreen(br);
		dinf.GetDC()->Rectangle(p1.x,p1.y,p2.x,p2.y);
		}
		else
		{
		
			UnitVector3D uvect;
			Vector3D vect1,vect3;
			Point3D tpnt1,tpnt2;
			mat.GetLocalLeftInWorld(&uvect);
			vect1.Multiply(uvect,obbTmp.axisExtents.x);
			
			
			mat.GetLocalForwardInWorld(&uvect);
			vect3.Multiply(uvect,obbTmp.axisExtents.z);
			CPoint start;
			

			tpnt1.Add(center,vect1);
			tpnt2.Add(tpnt1,vect3);
			start=dinf.vinf.DataToScreen(tpnt2);
			dinf.GetDC()->MoveTo(start);
			tpnt2.Subtract(tpnt1,vect3);
			dinf.GetDC()->LineTo(dinf.vinf.DataToScreen(tpnt2));
			
			tpnt1.Subtract(center,vect1);
			tpnt2.Subtract(tpnt1,vect3);
			dinf.GetDC()->LineTo(dinf.vinf.DataToScreen(tpnt2));
			tpnt2.Add(tpnt1,vect3);
			dinf.GetDC()->LineTo(dinf.vinf.DataToScreen(tpnt2));
			dinf.GetDC()->LineTo(start);
			
			
		}	
		}
		else
		{
		
			UnitVector3D uvect;
			Vector3D vect1,vect2,vect3;
			Point3D tpnt,tpnt2,tpnt3;
			mat.GetLocalLeftInWorld(&uvect);
			vect1.Multiply(uvect,obbTmp.axisExtents.x);
			
			mat.GetLocalUpInWorld(&uvect);
			vect2.Multiply(uvect,obbTmp.axisExtents.y);
			
			mat.GetLocalForwardInWorld(&uvect);
			vect3.Multiply(uvect,obbTmp.axisExtents.z);
			CPoint pnts[8];
			
			tpnt.Add(center,vect1);
			tpnt2.Add(tpnt,vect2);
			tpnt3.Add(tpnt2,vect3);
			pnts[0]=dinf.vinf.DataToScreen(tpnt3);
			tpnt3.Subtract(tpnt2,vect3);
			pnts[1]=dinf.vinf.DataToScreen(tpnt3);
			
			tpnt2.Subtract(tpnt,vect2);
			tpnt3.Add(tpnt2,vect3);
			pnts[2]=dinf.vinf.DataToScreen(tpnt3);
			tpnt3.Subtract(tpnt2,vect3);
			pnts[3]=dinf.vinf.DataToScreen(tpnt3);
			
			tpnt.Subtract(center,vect1);
			tpnt2.Add(tpnt,vect2);
			tpnt3.Add(tpnt2,vect3);
			pnts[4]=dinf.vinf.DataToScreen(tpnt3);
			tpnt3.Subtract(tpnt2,vect3);
			pnts[5]=dinf.vinf.DataToScreen(tpnt3);
			
			tpnt2.Subtract(tpnt,vect2);
			tpnt3.Add(tpnt2,vect3);
			pnts[6]=dinf.vinf.DataToScreen(tpnt3);
			tpnt3.Subtract(tpnt2,vect3);
			pnts[7]=dinf.vinf.DataToScreen(tpnt3);
			
			
			dinf.GetDC()->MoveTo(pnts[0]);
			dinf.GetDC()->LineTo(pnts[1]);
			dinf.GetDC()->LineTo(pnts[3]);
			dinf.GetDC()->LineTo(pnts[2]);
			dinf.GetDC()->LineTo(pnts[0]);
			
			dinf.GetDC()->LineTo(pnts[4]);
			dinf.GetDC()->LineTo(pnts[5]);
			dinf.GetDC()->LineTo(pnts[7]);
			dinf.GetDC()->LineTo(pnts[6]);
			dinf.GetDC()->LineTo(pnts[4]);
			
			dinf.GetDC()->MoveTo(pnts[1]);
			dinf.GetDC()->LineTo(pnts[5]);
			
			dinf.GetDC()->MoveTo(pnts[3]);
			dinf.GetDC()->LineTo(pnts[7]);

			dinf.GetDC()->MoveTo(pnts[2]);
			dinf.GetDC()->LineTo(pnts[6]);

		}
	
  }
	else
	{	
		EdGUIObject::Draw(dinf);
		if(MyEntity->IsDerivedFrom(WaterCultural::DefaultData))
		{
			int rad=GetScreenRadius(dinf.vinf);
			CPoint spnt,pnt=dinf.vinf.DataToScreen(GetPos());
			
			CDC *pDC=dinf.GetDC();
			CRect rct;
			CPoint pstart;
			CPoint pend;
			int clines=3;
			for(int lnum=0;lnum<clines;lnum++)
			{
				rct.left=pnt.x-rad;
				rct.right=pnt.x;
				rct.top=(pnt.y-rad)+(lnum*rad*2)/clines;
				rct.bottom=(pnt.y-rad)+((lnum+1)*rad*2)/clines;
				pstart.x=rct.left;
				pstart.y=rct.CenterPoint().y;
				pend.x=rct.right;
				pend.y=rct.CenterPoint().y;
				pDC->SetArcDirection(AD_CLOCKWISE);
				pDC->Arc(&rct,pstart,pend);
				
				rct.left=pnt.x;
				rct.right=pnt.x+rad;
				rct.top=(pnt.y-rad)+(lnum*rad*2)/clines;
				rct.bottom=(pnt.y-rad)+((lnum+1)*rad*2)/clines;
				pstart.x=rct.left;
				pstart.y=rct.CenterPoint().y;
				pend.x=rct.right;
				pend.y=rct.CenterPoint().y;
				pDC->SetArcDirection(AD_COUNTERCLOCKWISE);
				pDC->Arc(&rct,pstart,pend);
			}
			
		}
	}
	
}

void EdGameObject::GetMultiProps(CObjProps *props)
{
	props->SetModTagFrom(this);
}

void EdGameObject::SetMultiProps(CObjProps *props,UndoCommand **cmd)
{
	props->SetData(this,cmd);
}

bool EdGameObject::HasLocalizedName()
{
	if(!MyEntity) return false;
	Check_Object(MyEntity);
	if (MyEntity->IsDerivedFrom(MWObject::DefaultData))
	{
		MechWarrior4::MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
		return mwobject->m_doesHaveInstanceName;
	}
	else
	{
		return false;
	}
	
}

void EdGameObject::UseLocalizedName(bool flag)
{
	if (MyEntity && MyEntity->IsDerivedFrom(MWObject::DefaultData))
	{
		Check_Object(MyEntity);
		MechWarrior4::MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
		mwobject->m_doesHaveInstanceName=flag;
	}
}

void EdGameObject::FillSkinList(CComboBox *ctrl)
{
ctrl->ResetContent();
int i,itm;
	if(MyEntity && MyEntity->IsDerivedFrom(Mech::DefaultData))
	{
	for(i=0;i<GetSkinCount();i++)
		{
		itm=ctrl->AddString(GetNthSkinName(i));
		ctrl->SetItemData(itm,GetNthSkin(i));
		}
	}
	/*
	else if(MyEntity && MyEntity->IsDerivedFrom(Vehicle::DefaultData))
	{
	for(i=0;i<2;i++) ctrl->AddString(SkinToText(i));
	}
	*/

}



CString EdGameObject::SkinToText(char  skin)
{
return GetSkinName(skin);
/*
	if(MyEntity && MyEntity->IsDerivedFrom(Mech::DefaultData))
	{
	switch(skin)
	{
	case DefaultSkin: return ("Default Skin"); break;
	case LunarFriend: return ("Lunar Friend"); break;
	case LunarEnemy:  return ("Lunar Enemy"); break;
	case ArticFriend: return ("Artic Friend"); break;
	case ArticEnemy:  return ("Artic Enemy"); break;
	case AlpineFriend:return ("Alpine Friend"); break;
	case AlpineEnemy: return ("Alpine Enemy"); break;
	case DesertFriend:return ("Desert Friend"); break;
	case DesertEnemy: return ("Desert Enemy"); break;
	case SwampFriend: return ("Swamp Friend"); break;
	case SwampEnemy:  return ("Swamp Enemy"); break;	
		
	}
	}
*/
  /*	
	else 
	if(MyEntity && MyEntity->IsDerivedFrom(Vehicle::DefaultData))
	{
	switch(skin)
	{
	case VehicleEnemySkin: return ("Vehicle Enemy"); break;
	case VehicleFriendlySkin: return ("Vehicle Friendly"); break;
	}
	}
	*/
	
	return ("UnSkinable"); 
}

bool EdGameObject::IsInvulnerable()
{
	if (MyEntity->IsDerivedFrom(MWObject::DefaultData))
	{
		MechWarrior4::MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
		Check_Object(mwobject);
		return mwobject->invulnerable;
	}
	return false;
}

void EdGameObject::SetInvulnerable(bool inv)
{
	if (MyEntity->IsDerivedFrom(MWObject::DefaultData))
	{
		MechWarrior4::MWObject* mwobject = Cast_Object(MWObject*,MyEntity);
		Check_Object(mwobject);
		mwobject->invulnerable=inv;

		// If object is vulnerable and has no damage object
		// rebuild from content and get the damage resource id
		if (!mwobject->invulnerable && mwobject->damageStreamResourceID == ResourceID::Null)
		{
			EdGameObject* obj = new EdGameObject();
			obj->BuildFrom(ResourcePath, CString("@#test213"));
			
			ASSERT(obj->MyEntity->IsDerivedFrom(MWObject::DefaultData));
			MechWarrior4::MWObject* newmwobject = Cast_Object(MWObject*,obj->MyEntity);
			mwobject->damageStreamResourceID = newmwobject->damageStreamResourceID;
			delete obj;
		}
	}
}

void EdGameObject::SaveTextInfo(NotationFile *not_file)
{
	EdGUIObject::SaveTextInfo(not_file);
	if(IsInvulnerable())
	{
	Page *page=not_file->SetPage((char *)(LPCSTR)GetName());
	page->SetEntry("Invulnerable",true);
	}
}

void EdGameObject::SetInfo(Page *page)
{
	EdGUIObject::SetInfo(page);
	bool inv;
	if(page->GetEntry("Invulnerable",&inv)) SetInvulnerable(inv);


}
