Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

1742 lines
40 KiB
C++

#include "MW4Headers.hpp"
#include "Flag.hpp"
#include "ai.hpp"
#include "Mech.hpp"
#include "MWApplication.hpp"
#include "bucket.hpp"
#include "MWMission.hpp"
#include "aiutils.hpp"
#include "rail_move.hpp"
#include "torso.hpp"
#include <Adept\DropZone.hpp>
#include <Adept\EntityClassData.hpp>
#include <Adept\Site.hpp>
#include <Adept\CollisionGrid.hpp>
#include <Adept\Map.hpp>
#include "team.hpp"
#include <ElementRenderer\Element.hpp>
#include <Adept\Renderer.hpp>
#include <MissionLang\Resource.h>
#include "nglog_mw4.hpp"
// jcem - start
#include "windows.h"
#include "ctcls.h"
#include "ctcl.h"
#include "recscore.h" // jcem
// jcem - end
//#############################################################################
//############################### Flag ##############################
//#############################################################################
Flag::ClassData* Flag::DefaultData = NULL;
const Stuff::Scalar FLAG_DISTANCE = 25.0f;
const Stuff::Scalar FLAG_DROP_DISTANCE = 80.0f;
const Stuff::Scalar FLAG_MAX_IDLE_TIME = 30.0f;
const Stuff::Scalar flag_hold_increment_time = 1.0f;
const Stuff::Scalar flag_drop_behind_distance = 10.0f;
//________________________________________________________________________________________________________________
void Flag::InitializeClass()
{
Verify(!DefaultData);
DefaultData =
new ClassData(
FlagClassID,
"MechWarrior4::Flag",
BaseClass::DefaultData,
0, NULL,
(BaseClass::Factory)Make,
(BaseClass::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
ExecutionStateEngine::DefaultData,
(BaseClass::GameModel::Factory)GameModel::ConstructGameModel,
(BaseClass::GameModel::Factory)GameModel::ConstructOBBStream,
(BaseClass::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
(BaseClass::GameModel::ModelWrite)GameModel::WriteToText,
(BaseClass::GameModel::ModelSave)GameModel::SaveGameModel,
AnimationStateEngine::Make
);
Register_Object(DefaultData);
}
//________________________________________________________________________________________________________________
void Flag::TerminateClass()
{
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//________________________________________________________________________________________________________________
Flag* Flag::Make(CreateMessage *message,ReplicatorID *base_id)
{
Check_Object(message);
Flag *new_entity =
new Flag(DefaultData, message, base_id, NULL);
Check_Object(new_entity);
return new_entity;
}
//________________________________________________________________________________________________________________
Flag::Flag(ClassData *class_data,CreateMessage *message,ReplicatorID *base_id,ElementRenderer::Element *element)
: NavPoint(class_data, message, base_id, element)
, m_AttachedTo (NULL)
, m_Team(MWApplication::No_Team)
, m_Origin(LinearMatrix4D::Identity)
, m_DeactiveTime(0)
, m_WaitAfterCaptureTime(0)
, m_AttachRadius(FLAG_DISTANCE)
, m_FirstFrame(true)
, m_HoldTimeLastUpdate(0)
, m_Visible(true)
, m_LastFlagEvent(FLAG_NONE)
{
Check_Pointer(this);
Check_Object(message);
executionState->RequestState(ExecutionStateEngine::AlwaysExecuteState);
int team(MWApplication::NameToTeamNumber(instanceName));
if (team != MWApplication::No_Team)
{
SetTeam(team);
}
m_UseDropNames = UseDropNames();
m_LastAnimateTime = -10.0f;
m_DisplayIncValue = -1; // starts at -1 forcing a -1 value to become 0 for visualrepresentation
SetToDisplay();
}
//________________________________________________________________________________________________________________
Flag::~Flag()
{
}
//________________________________________________________________________________________________________________
void Flag::RevealFlag()
{
Check_Object(this);
if (m_Visible == false)
{
SetVisibleFlag();
SetNewLocalToParent(m_Origin);
SyncMatrices(true);
Map::GetInstance()->UpdateZone(this);
m_Visible = true;
// executionState->RequestState(ExecutionStateEngine::AlwaysExecuteState);
MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
if (mwmission->GetFlagsAsNavPoints() == true)
{
AddToNavList();
}
else
{
RemoveFromNavList();
}
}
}
void Flag::HideFlag()
{
m_HoldTimeLastUpdate = 0;
if (m_Visible == true)
{
ClearVisibleFlag();
Stuff::LinearMatrix4D m(GetLocalToWorld());
m.BuildTranslation(Stuff::Point3D::HellPoint);
SetNewLocalToParent(m);
SyncMatrices(true);
Map::GetInstance()->UpdateZone(this);
m_Visible = false;
// executionState->RequestState(ExecutionStateEngine::NeverExecuteState);
RemoveFromNavList();
IgnorePostCollision();
}
}
//________________________________________________________________________________________________________________
void Flag::TestInstance() const
{
Verify(IsDerivedFrom(DefaultData));
}
void Flag::Attach (Adept::Entity *who)
{
if (Attached() == who)
return;
if (who == 0)
{
m_HoldTimeLastUpdate = 0;
}
m_AttachedTo.Remove ();
if ((who) &&
(m_Visible == true))
{
Check_Object (who);
m_StartAttachTime = gos_GetElapsedTime ();
m_AttachedTo.Add (who);
MWObject *obj;
obj = Cast_Object (MWObject *, who);
m_AttachSite = obj->FindSite("site_flag");
if (!m_AttachSite)
m_AttachSite = obj->FindSite ("site_eject");
if (!m_AttachSite)
{
Attach (NULL);
}
}
}
//________________________________________________________________________________________________________________
Stuff::Time Flag::TimeAttached()
{
if (Attached())
{
return gos_GetElapsedTime () - m_StartAttachTime;
}
return 0;
}
//________________________________________________________________________________________________________________
Adept::Entity* Flag::Attached()
{
return m_AttachedTo.GetCurrent();
}
//________________________________________________________________________________________________________________
void Flag::PreCollisionExecute(Stuff::Time till)
{
PRECOLLISION_LOGIC("Flag");
if (m_FirstFrame == true)
{
BaseClass::PreCollisionExecute (till);
m_Origin = GetLocalToWorld();
m_FirstFrame = false;
return;
}
if (Enabled() == false)
{
Attach(NULL);
HideFlag();
return;
}
if (m_WaitAfterCaptureTime != 0)
{
UpdateWaitAfterCapture();
}
else
{
RevealFlag();
UsePostCollision ();
if (Network::GetInstance()->AmIServer())
{
if (Attached() == 0)
{
UpdateUnattached();
}
else
{
UpdateAttached();
}
}
}
if (m_Visible == true)
{
if (gos_GetElapsedTime () - m_LastAnimateTime > (1.0f/10.0f)) // six animations per second
{
m_LastAnimateTime = (float)gos_GetElapsedTime ();
visualRepresentation += m_DisplayIncValue;
if (visualRepresentation <= FirstFlagAnimationState)
{
visualRepresentation = FirstFlagAnimationState;
m_DisplayIncValue = 1;
}
else if (visualRepresentation >= SixthFlagAnimationState)
{
visualRepresentation = SixthFlagAnimationState;
m_DisplayIncValue = -1;
}
ExecuteComponentWebs();
}
BaseClass::PreCollisionExecute (till);
}
}
//________________________________________________________________________________________________________________
void Flag::UpdateUnattached()
{
if ((m_DeactiveTime != 0) &&
(GetFlagDropReturnTime() != -1) &&
(gos_GetElapsedTime() > m_DeactiveTime))
{
// ngLog addition
#if !defined(NO_LOG)
if(m_Team != MWApplication::No_Team) {
MW4log_generic(MW4P_DSTATS, va("Flag_Return\t-1\t%d", m_Team));
}
#endif // !defined(NO_LOG)
Execute_ReturnToOrigin();
return;
}
LookForSomeoneToAttachTo();
}
//________________________________________________________________________________________________________________
void Flag::LookForSomeoneToAttachTo()
{
NameTable *table = NameTable::GetInstance();
// For Bots?
// MSL 5.05 Team Return Flag
int size(table->nameTableArray[NameTable::VehicleArray].GetLength());
{
for (int i = 0; i < size; ++i)
{
NameTableEntry *data;
data = &table->nameTableArray [NameTable::VehicleArray][i];
Adept::Entity* ent = data->dataPointer->GetCurrent ();
if ((ent != 0) ||
(EntityCanCarryMe(*ent) == true))
{
if (IsWithin(ent,m_AttachRadius,true) == true)
{
if (EntityCanCarryMe(*ent) == true)
{
Execute_AttachTo(ent);
return;
}
}
}
}
}
size = table->nameTableArray[NameTable::VehicleArray].GetLength();
{
for (int i = 0; i < size; ++i)
{
NameTableEntry *data;
data = &table->nameTableArray [NameTable::VehicleArray][i];
Adept::Entity* ent = data->dataPointer->GetCurrent ();
if ((ent != 0) ||
(EntityCanReturnMe(*ent) == true))
{
if (IsWithin(ent,m_AttachRadius,true) == true)
{
if (EntityCanReturnMe(*ent) == true)
{
SetNewLocalToParent(m_Origin);
m_DeactiveTime = 0;
return;
}
}
}
}
}
}
/*
// Original Flag Code
//________________________________________________________________________________________________________________
void Flag::LookForSomeoneToAttachTo()
{
NameTable *table = NameTable::GetInstance();
int size(table->nameTableArray[NameTable::VehicleArray].GetLength());
{for (int i = 0;
i < size;
++i)
{
NameTableEntry *data;
data = &table->nameTableArray [NameTable::VehicleArray][i];
Adept::Entity* ent = data->dataPointer->GetCurrent ();
if ((ent == 0) ||
(EntityCanCarryMe(*ent) == false))
{
continue;
}
if (IsWithin(ent,m_AttachRadius,true) == true)
{
Execute_AttachTo(ent);
return;
}
}}
size = table->nameTableArray[NameTable::PlayerArray].GetLength();
{for (int i = 0;
i < size;
++i)
{
NameTableEntry *data;
data = &table->nameTableArray [NameTable::PlayerArray][i];
Adept::Entity* ent = data->dataPointer->GetCurrent ();
if ((ent != 0) &&
(ent->IsDerivedFrom(Adept::Player::DefaultData) == true))
{
Adept::Player* player = Cast_Object(Adept::Player*,ent);
if (player->vehicle != 0)
{
if (EntityCanCarryMe(*(player->vehicle)) == false)
{
continue;
}
if (IsWithin(player->vehicle,m_AttachRadius,true) == true)
{
Execute_AttachTo(player->vehicle);
return;
}
}
}
}}
}
*/
//________________________________________________________________________________________________________________
void Flag::UpdateAttached()
{
Verify(Attached() != 0);
if (CarrierCanStillCarryMe() == false)
{
Execute_Drop();
}
else
{
if (CarrierCanCaptureMe() == true)
{
Execute_Capture();
}
else
{
if (m_HoldTimeLastUpdate == 0)
{
m_HoldTimeLastUpdate = (Stuff::Scalar)gos_GetElapsedTime();
}
if (m_HoldTimeLastUpdate + flag_hold_increment_time < (Stuff::Scalar)gos_GetElapsedTime())
{
m_HoldTimeLastUpdate += flag_hold_increment_time;
IncrementScore(CBucketManager::FLAG_HOLD_TIME,Attached()->GetReplicatorID());
}
}
}
}
//________________________________________________________________________________________________________________
void Flag::UpdateWaitAfterCapture()
{
Verify(m_WaitAfterCaptureTime != 0);
if (m_WaitAfterCaptureTime < 0)
{
HideFlag();
return;
}
if (gos_GetElapsedTime() > m_WaitAfterCaptureTime)
{
m_WaitAfterCaptureTime = 0;
RevealFlag();
}
}
//________________________________________________________________________________________________________________
void Flag::PostCollisionExecute(Stuff::Time till)
{
POSTCOLLISION_LOGIC("Flag");
if (Attached() == 0)
{
UpdateFlagObjectOnGround();
}
else
{
if (Attached()->IsDestroyed ())
{
Execute_Drop();
}
else
{
UpdateFlagObjectAttached();
}
}
SyncMatrices(true);
BaseClass::PostCollisionExecute (till);
}
//________________________________________________________________________________________________________________
void Flag::UpdateFlagObjectOnGround()
{
Verify(Attached() == 0);
LinearMatrix4D mat(GetLocalToWorld ());
Stuff::Line3D line;
line.m_length = 2000.0f;
line.m_direction = Vector3D::Down;
line.m_origin = mat;
line.m_origin.y += 1000.0f;
Stuff::Normal3D normal;
CollisionQuery query(&line, &normal, CanBeWalkedOnFlag, this);
Check_Object(CollisionGrid::Instance);
CollisionGrid::Instance->ProjectLine(&query); // there had to be a unit here so it must hit something
Point3D tr;
line.FindEnd(&tr);
Point3D loc (GetLocalToWorld ());
loc.y = tr.y;
YawPitchRoll new_rotation(YawPitchRoll::Identity);
new_rotation = (YawPitchRoll) GetLocalToWorld ();
mat.BuildTranslation(loc);
mat.AlignLocalAxisToWorldVector (Vector3D::Up,Y_Axis,X_Axis,Z_Axis);
SetNewLocalToParent(mat);
}
//________________________________________________________________________________________________________________
void Flag::UpdateFlagObjectAttached()
{
Verify(Attached() != 0);
Check_Object(m_AttachSite);
LinearMatrix4D mat;
if (Attached()->IsDerivedFrom(MWObject::DefaultData) == true)
{
MWObject* mwobject = Cast_Object(MWObject*,Attached());
if (mwobject->GetTorso() != 0)
{
mat = mwobject->GetTorso()->GetTwistJointMatrix();
}
}
else
{
mat = Attached()->GetLocalToWorld();
}
UnitVector3D dir;
mat.GetLocalForwardInWorld(&dir);
EulerAngles ea(mat);
mat.BuildRotation(ea);
if (m_AttachSite != 0)
{
mat.BuildTranslation((Stuff::Point3D)m_AttachSite->GetLocalToWorld());
}
else
{
// put the flag in front and to the right of us
Point3D forward(dir);
forward *= 6.0f;
UnitVector3D unit_right;
Attached()->GetLocalToWorld().GetLocalRightInWorld(&unit_right);
Point3D right(unit_right);
right *= (4.0f + (Stuff::Scalar)GetMyIndex());
forward += right;
forward += (Point3D)mat;
mat.BuildTranslation(forward);
}
SetNewLocalToParent(mat);
}
//________________________________________________________________________________________________________________
int Flag::GetTeam() const
{
return (m_Team);
}
//________________________________________________________________________________________________________________
void Flag::SetTeam(int team)
{
Verify(team >= 0);
Verify(team <= 7);
m_Team = team;
}
//________________________________________________________________________________________________________________
inline std::string TeamNumToStr(int team_num)
{
char buf[100];
// MSL 5.02 Flag Team Name
if (team_num == 0)
sprintf(buf,"Blue");
if (team_num == 1)
sprintf(buf,"Red");
if (team_num == 2)
sprintf(buf,"Yellow");
if (team_num == 3)
sprintf(buf,"Green");
// sprintf(buf,"%d",team_num + 1);
return (buf);
}
//________________________________________________________________________________________________________________
void Flag::Notify(const std::string& s)
{
MWApplication::GetInstance()->SendChat(
Connection::Local->GetID(),
MWApplication::SystemBroadcast,
0,
(char*)s.c_str());
}
void AddNameAndOrTeam(std::string& s, int team_number, const char* string_name)
{
if (string_name != 0)
{
s += string_name;
if (team_number != MWApplication::No_Team)
{
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_TEAM1);//" (Team "
s += TeamNumToStr(team_number);
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_TEAM2);//")"
}
}
else
{
if (team_number != MWApplication::No_Team)
{
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_TEAM3);//"Team "
s += TeamNumToStr(team_number);
}
}
}
//________________________________________________________________________________________________________________
void Flag::NotifyFlagTaken(int flag_team, int taker_team, const char* taker_name)
{
// TODO: notify the team that their flag was picked up
std::string s;
if (flag_team == MWApplication::No_Team)
{
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_FLAG_TAKEN_BY);//"Flag Taken By ";
}
else
{
// MSL 5.02 Flag Notification Change
// s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_TEAM3);//"Team ";
s += TeamNumToStr(flag_team);
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_S_FLAG_TAKEN_BY);//" Flag Taken By ";
}
AddNameAndOrTeam(s,taker_team,taker_name);
Notify(s);
}
//________________________________________________________________________________________________________________
void Flag::NotifyFlagDropped(int flag_team, int dropper_team, const char* dropper_name)
{
// TODO: notify the team that their flag was dropped by its carrier
std::string s;
if (flag_team == MWApplication::No_Team)
{
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_FLAG_DROPPED_BY);//"Flag Dropped By ";
}
else
{
// MSL 5.02 Flag Notification Change
// s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_TEAM3);//"Team ";
s += TeamNumToStr(flag_team);
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_S_FLAG_DROPPED_BY);//" Flag Dropped By ";
}
AddNameAndOrTeam(s,dropper_team,dropper_name);
Notify(s);
}
//________________________________________________________________________________________________________________
void Flag::NotifyFlagCaptured(int flag_team, int capturer_team, const char* capturer_name)
{
// TODO: notify the team that their flag was taken to another team's drop zone
std::string s;
if (flag_team == MWApplication::No_Team)
{
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_FLAG_CAPTURED_BY);//"Flag Captured By ";
}
else
{
// MSL 5.02 Flag Notification Change
// s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_TEAM3);//"Team ");
s += TeamNumToStr(flag_team);
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_S_FLAG_CAPTURED_BY);//" Flag Captured By ";
}
AddNameAndOrTeam(s,capturer_team,capturer_name);
Notify(s);
}
//________________________________________________________________________________________________________________
void Flag::NotifyFlagReturned(int flag_team)
{
// TODO: notify the team that their flag was returned to their base due to time-out
std::string s;
// MSL 5.02 Flag Notification Change
// std::string s(Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_TEAM3));//"Team ");
s += TeamNumToStr(flag_team);
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_S_FLAG_RETURNED_TO_BASE);//" Flag Returned To Base";
Notify(s);
}
//________________________________________________________________________________________________________________
bool Flag::UseDropNames()
{
{for (int i = 0;
i < NameTable::GetInstance()->GetLength(NameTable::DropZoneArray);
++i)
{
NameTableEntry* table_entry = NameTable::GetInstance()->FindEntry(NameTable::DropZoneArray,i);
if (table_entry != 0)
{
int team_number(FlagDropNameToTeamNumber(table_entry->objectName));
if (team_number != MWApplication::No_Team)
{
return (true);
}
}
}}
return (false);
}
//________________________________________________________________________________________________________________
bool Flag::CanDropTeamFlagHere(int team)
{
{
for (int i = 0;
i < NameTable::GetInstance()->GetLength(NameTable::DropZoneArray);
++i)
{
NameTableEntry* table_entry = NameTable::GetInstance()->FindEntry(NameTable::DropZoneArray,i);
if ((table_entry != 0) &&
(table_entry->dataPointer != 0) &&
(table_entry->dataPointer->GetCurrent() != 0)&&
(table_entry->dataPointer->GetCurrent()->IsDerivedFrom(DropZone::DefaultData) == true))
{
DropZone* drop_zone = Cast_Object(DropZone*,table_entry->dataPointer->GetCurrent());
int team_number;
if (m_UseDropNames == true)
{
team_number = FlagDropNameToTeamNumber(drop_zone->instanceName);
}
else
{
team_number = MWApplication::NameToTeamNumber(drop_zone->instanceName);
}
// MSL 5.06 Edit for other flag being carried here!!
if (team_number == team)
{
return (drop_zone->IsWithin(this,FLAG_DROP_DISTANCE,true));
}
}
}
}
return (false);
}
//________________________________________________________________________________________________________________
void Flag::GetFlagsCarriedBy(Adept::Entity& entity, std::vector<Flag*>& flags)
{
int num_flags = NameTable::GetInstance()->GetLength(NameTable::FlagArray);
{for (int i = 0;
i < num_flags;
++i)
{
NameTableEntry* entry = NameTable::GetInstance()->FindEntry(NameTable::FlagArray,i);
if ((entry != 0) &&
(entry->dataPointer != 0) &&
(entry->dataPointer->GetCurrent() != 0) &&
(entry->dataPointer->GetCurrent()->IsDerivedFrom(Flag::DefaultData) == true))
{
Flag* flag = Cast_Object(Flag*,entry->dataPointer->GetCurrent());
if (flag->Attached() == &entity)
{
flags.push_back(flag);
}
}
}}
}
//________________________________________________________________________________________________________________
int Flag::NumFlagsCarriedBy(Adept::Entity& entity)
{
std::vector<Flag*> flags;
GetFlagsCarriedBy(entity, flags);
return (flags.size());
}
//________________________________________________________________________________________________________________
bool Flag::EntityCanCarryMe(Adept::Entity& entity)
{
if (Attached() != 0)
{
return (false);
}
if ((entity.IsDestroyed() == true) ||
(entity.IsDerivedFrom(Mech::DefaultData) == false))
{
return (false);
}
Mech* mech = Cast_Object(Mech*,&entity);
if (GetTeam() != MWApplication::No_Team)
{
if (mech->GetTeam() == GetTeam())
{
return (false);
}
}
if (mech->IsShutdown() == true)
{
return (false);
}
int max_flags = mech->GetMaxFlagsCarried();
if (max_flags < 1)
{
return (false);
}
if (NumFlagsCarriedBy(entity) >= max_flags)
{
return (false);
}
const Stuff::Point3D my_pos(GetLocalToWorld());
if (GetSquaredDistToMatrixForward(my_pos,mech->GetLocalToWorld()) >
GetSquaredDistToMatrixBackward(my_pos,mech->GetLocalToWorld()))
{
return (false);
}
return (true);
}
//________________________________________________________________________________________________________________
bool Flag::EntityCanReturnMe(Adept::Entity& entity)
{
if (Attached() != 0)
{
return (false);
}
if ((entity.IsDestroyed() == true) ||
(entity.IsDerivedFrom(Mech::DefaultData) == false))
{
return (false);
}
Mech* mech = Cast_Object(Mech*,&entity);
if (GetTeam() != MWApplication::No_Team)
{
if (mech->GetTeam() == GetTeam())
{
return (true);
}
}
if (mech->IsShutdown() == true)
{
return (false);
}
int max_flags = mech->GetMaxFlagsCarried();
if (max_flags < 1)
{
return (false);
}
if (NumFlagsCarriedBy(entity) >= max_flags)
{
return (false);
}
const Stuff::Point3D my_pos(GetLocalToWorld());
if (GetSquaredDistToMatrixForward(my_pos,mech->GetLocalToWorld()) >
GetSquaredDistToMatrixBackward(my_pos,mech->GetLocalToWorld()))
{
return (false);
}
return (false);
}
//________________________________________________________________________________________________________________
void Flag::Execute_ReturnToOrigin()
{
SetNewLocalToParent(m_Origin);
Broadcast_FlagReturned();
if (m_Team != MWApplication::No_Team)
{
NotifyFlagReturned(m_Team);
}
m_DeactiveTime = 0;
}
//________________________________________________________________________________________________________________
void Flag::Execute_AttachTo(Adept::Entity* entity)
{
Verify(Attached() == 0);
Verify(entity != 0);
IncrementScore(CBucketManager::FLAGS_TAKEN,entity->GetReplicatorID());
#if !defined(NO_LOG)
MW4log_generic(MW4P_DSTATS, va("Flag_Taken\t%d", entity->GetReplicatorID().connectionID));
#endif // !defined(NO_LOG)
m_HoldTimeLastUpdate = (Stuff::Scalar)gos_GetElapsedTime();
Attach(entity);
if (Attached() != 0)
{
Vehicle* vehicle = Cast_Object(Vehicle*,entity);
NotifyFlagTaken(m_Team,vehicle->GetTeam(),vehicle->instanceName);
Broadcast_FlagTaken(*vehicle);
}
}
//________________________________________________________________________________________________________________
void Flag::Execute_Drop()
{
Verify(Attached() != 0);
m_HoldTimeLastUpdate = 0;
Stuff::LinearMatrix4D matrix(Attached()->GetLocalToWorld());
Stuff::Scalar desired_height = ((Stuff::Point3D)matrix).y;
Stuff::UnitVector3D unit_backwards;
matrix.GetLocalBackwardInWorld(&unit_backwards);
Stuff::Point3D backwards(unit_backwards);
backwards *= flag_drop_behind_distance;
backwards += (Stuff::Point3D)matrix;
FindGoodDropSpot(backwards,desired_height);
matrix.BuildTranslation(backwards);
SetNewLocalToParent(matrix);
SyncMatrices(true);
Map::GetInstance()->UpdateZone(this);
IncrementScore(CBucketManager::FLAGS_DROPPED,Attached()->GetReplicatorID());
#if !defined(NO_LOG)
MW4log_generic(MW4P_DSTATS, va("Flag_Drop\t%d", Attached()->GetReplicatorID().connectionID));
#endif // !defined(NO_LOG)
Vehicle* vehicle = Cast_Object(Vehicle*,Attached());
Check_Object(vehicle);
NotifyFlagDropped(m_Team,vehicle->GetTeam(),vehicle->instanceName);
Attach (NULL);
switch (GetFlagDropReturnTime())
{
case 0:
{
// ngLog addition
#if !defined(NO_LOG)
if(m_Team != MWApplication::No_Team) {
MW4log_generic(MW4P_DSTATS, va("Flag_Return\t-1\t%d", m_Team));
}
#endif // !defined(NO_LOG)
Execute_ReturnToOrigin();
break;
}
case -1:
{
return;
}
default:
{
m_DeactiveTime = gos_GetElapsedTime() + GetFlagDropReturnTime();
}
}
}
//________________________________________________________________________________________________________________
bool Flag::CarrierCanStillCarryMe()
{
Verify(Attached() != 0);
if ((Attached()->IsDestroyed() == true) ||
(Attached()->IsDerivedFrom(Mech::DefaultData) == false))
{
return (false);
}
if (GetTeam() != MWApplication::No_Team)
{
Mech* mech = Cast_Object(Mech*,Attached());
if (mech->GetTeam() == GetTeam())
{
return (false);
}
}
Mech* mech = Cast_Object(Mech*,Attached());
if (mech->IsShutdown() == true)
{
return (false);
}
return (true);
}
//________________________________________________________________________________________________________________
bool Flag::CarrierCanCaptureMe()
{
Verify(Attached() != 0);
Verify(Attached()->IsDerivedFrom(Mech::DefaultData) == true);
MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
if (mwmission->GetFlagCaptureEnabled() == false)
{
return (false);
}
Mech* mech = Cast_Object(Mech*,Attached());
if (GetTeam() == MWApplication::No_Team)
{
return (CanDropTeamFlagHere(mech->GetTeam()));
}
else
{
if (mech->GetTeam() != GetTeam())
{
return (CanDropTeamFlagHere(mech->GetTeam()));
}
}
return (false);
}
//________________________________________________________________________________________________________________
void Flag::Execute_Capture()
{
Verify(Attached() != 0);
IncrementScore(CBucketManager::FLAGS_CAPTURED,Attached()->GetReplicatorID());
g_RSF.RecScore(CBucketManager::FLAGS_CAPTURED,Attached()->GetReplicatorID()); // jcem
#if !defined(NO_LOG)
MW4log_generic(MW4P_DSTATS, va("Flag_Capture\t%d", Attached()->GetReplicatorID().connectionID));
#endif // !defined(NO_LOG)
if (Attached()->IsDerivedFrom(Mech::DefaultData) == true)
{
Mech* mech = Cast_Object(Mech*,Attached());
NotifyFlagCaptured(m_Team,mech->GetTeam(),mech->instanceName);
}
m_HoldTimeLastUpdate = 0;
Broadcast_FlagCaptured();
Attach(NULL);
switch (GetFlagCaptureReturnTime())
{
case 0:
{
SetNewLocalToParent(m_Origin);
break;
}
case -1:
{
HideFlag();
m_WaitAfterCaptureTime = -1;
break;
}
default:
{
HideFlag();
m_WaitAfterCaptureTime = gos_GetElapsedTime() + GetFlagCaptureReturnTime();
break;
}
}
}
//________________________________________________________________________________________________________________
int Flag::FlagDropNameToTeamNumber(char* name) const
{
if (name == 0)
{
return (MWApplication::No_Team);
}
char buf[200];
strcpy(buf,name);
std::string s(_strlwr(buf));
std::string::size_type pos(s.find("teamcapture"));
if (pos != std::string::npos)
{
pos += 11;
if (pos < s.size())
{
s.erase(0,pos);
if (s.size() > 1)
{
s.erase(1,s.size() - 1);
}
char* stopstring;
long team_number(strtol(s.c_str(),&stopstring,10));
if (team_number == 0)
{
team_number = MWApplication::No_Team;
}
else
{
--team_number;
}
if ((team_number >= 0) &&
(team_number <= 7))
{
return (team_number);
}
}
}
return (MWApplication::No_Team);
}
//________________________________________________________________________________________________________________
int Flag::GetFlagDropReturnTime()
{
MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
return (mwmission->GetFlagDropReturnTime());
}
//________________________________________________________________________________________________________________
int Flag::GetFlagCaptureReturnTime()
{
MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
return (mwmission->GetFlagCaptureReturnTime());
}
//________________________________________________________________________________________________________________
int Flag::GetMyIndex()
{
Verify(Attached() != 0);
std::vector<Flag*> flags;
GetFlagsCarriedBy(*(Attached()),flags);
{for (int i = 0;
i < flags.size();
++i)
{
if (flags[i] == this)
{
return (i);
}
}}
Verify(!"Should never get here.");
return (0);
}
//________________________________________________________________________________________________________________
void Flag::IncrementScore(int bucket_type, const Adept::ReplicatorID& id)
{
MWMission *mission = Cast_Object(MWMission*,MWMission::GetInstance());
mission->m_BucketManager->NotifyAction((CBucketManager::Bucket_Type)bucket_type,id,1);
}
//________________________________________________________________________________________________________________
bool Flag::Enabled()
{
if (m_Team != MWApplication::No_Team)
{
if ((MWApplication::GetInstance() == 0) ||
(MWApplication::GetInstance()->TeamHasAnyPlayers(m_Team) == false))
{
return (false);
}
}
MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
switch (mwmission->GetFlagsEnabled())
{
case MWMission::FLAGS_HIDE:
{
return (false);
}
case MWMission::FLAGS_TEAM_ONLY:
{
return ((m_Team >= 0) && (m_Team <= 7));
}
case MWMission::FLAGS_UNIVERSAL_ONLY:
{
return (m_Team == MWApplication::No_Team);
}
case MWMission::FLAGS_SHOW_ALL:
{
return (true);
}
}
Verify(!"Enable state not found");
return (false);
}
//________________________________________________________________________________________________________________
void Flag::Respawn(Adept::Entity::CreateMessage *message)
{
Attach(NULL);
HideFlag();
SetNewLocalToParent(m_Origin);
m_DeactiveTime = 0;
m_WaitAfterCaptureTime = 0;
m_HoldTimeLastUpdate = 0;
if (message != 0)
{
Entity::Respawn(message);
}
}
//________________________________________________________________________________________________________________
void Flag::RemoveAllFlagsFrom(Adept::Entity& entity)
{
NameTable *table = NameTable::GetInstance();
if (table == 0)
{
return;
}
int size(table->nameTableArray[NameTable::FlagArray].GetLength());
{for (int i = 0;
i < size;
++i)
{
NameTableEntry *data = &table->nameTableArray [NameTable::FlagArray][i];
Adept::Entity* ent = data->dataPointer->GetCurrent();
if ((ent != 0) &&
(ent->IsDerivedFrom(Flag::DefaultData) == true))
{
Flag* flag = Cast_Object(Flag*,ent);
if (flag->Attached() == &entity)
{
flag->Execute_Drop();
}
}
}}
}
//________________________________________________________________________________________________________________
void Flag::ResetAllFlags()
{
NameTable *table = NameTable::GetInstance();
if (table == 0)
{
return;
}
int size(table->nameTableArray[NameTable::FlagArray].GetLength());
{for (int i = 0;
i < size;
++i)
{
NameTableEntry *data = &table->nameTableArray [NameTable::FlagArray][i];
Adept::Entity* ent = data->dataPointer->GetCurrent();
if ((ent != 0) &&
(ent->IsDerivedFrom(Flag::DefaultData) == true))
{
Flag* flag = Cast_Object(Flag*,ent);
if (flag->Attached() != 0)
{
flag->Attach(0);
}
}
}}
}
//________________________________________________________________________________________________________________
bool Flag::AnyFlagsAttachedTo(Adept::Entity& entity)
{
NameTable *table = NameTable::GetInstance();
if (table == 0)
{
return (false);
}
int size(table->nameTableArray[NameTable::FlagArray].GetLength());
{for (int i = 0;
i < size;
++i)
{
NameTableEntry *data = &table->nameTableArray [NameTable::FlagArray][i];
Adept::Entity* ent = data->dataPointer->GetCurrent();
if ((ent != 0) &&
(ent->IsDerivedFrom(Flag::DefaultData) == true))
{
Flag* flag = Cast_Object(Flag*,ent);
if (flag->Attached() == &entity)
{
return (true);
}
}
}}
return (false);
}
//________________________________________________________________________________________________________________
bool CouldDropAtPoint(const Stuff::Point3D& point, Stuff::Scalar desired_height, Adept::Entity* who)
{
Stuff::Scalar minZ, maxZ, minX, maxX;
Map::GetInstance()->GetMapExtents(&minZ,&maxZ,&minX,&maxX);
if ((point.x <= minX) ||
(point.x >= maxX) ||
(point.z <= minZ) ||
(point.z >= maxZ))
{
return (false);
}
if (MWMission::GetInstance()->GetMissionArea(point) != MWMission::InMissionArea)
{
return (false);
}
#pragma warning (disable : 4800)
if (MW4AI::CheckCanPass(MW4AI::g_MissionGraph->Passable(point.x,point.z),MW4AI::LEGPASS_FLAG) == true)
{
return (false);
}
#pragma warning (default : 4800)
Verify(Adept::Map::GetInstance() != 0);
Stuff::Line3D line;
line.m_length = 200.0f;
line.m_direction = Vector3D::Down;
line.m_origin = point;
line.m_origin.y += 50.0f;
Stuff::Normal3D normal;
Entity::CollisionQuery query(&line,&normal,Entity::CanBeWalkedOnFlag,who);
Check_Object(CollisionGrid::Instance);
if (CollisionGrid::Instance->ProjectLine(&query) != Adept::Map::GetInstance())
{
return (false);
}
Stuff::Point3D hit_spot;
line.FindEnd(&hit_spot);
if ((hit_spot.y < desired_height - 10) ||
(hit_spot.y > desired_height + 10))
{
return (false);
}
return (true);
}
void Flag::FindGoodDropSpot(Stuff::Point3D& point, Stuff::Scalar desired_height)
{
if (CouldDropAtPoint(point,desired_height,Attached()) == true)
{
return;
}
Stuff::Scalar move_distance = 8.0f;
{for (int i_x = 0;
i_x < 10;
++i_x)
{
Stuff::Scalar x_delta = move_distance * (Stuff::Scalar)i_x;
if (i_x & 0x01)
{
x_delta *= -1;
}
{for (int i_z = 0;
i_z < 10;
++i_z)
{
Stuff::Scalar z_delta = move_distance * (Stuff::Scalar)i_z;
if (i_z & 0x01)
{
z_delta *= -1;
}
Stuff::Point3D p(point.x + x_delta,point.y,point.z + z_delta);
if (CouldDropAtPoint(p,desired_height,Attached()) == true)
{
point = p;
return;
}
}}
}}
}
int
Flag::GetExecutionSlot()
{
return (Entity::GetExecutionSlot());
}
void
Flag::AddStatsToString(std::string& s)
{
s += instanceName;
if (GetTeam() != MWApplication::No_Team)
{
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_TEAM4);//"Team: ";
s += IntToString(m_Team);
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_SPACE_NEWLINE);//" \n";
}
if (Attached() != 0)
{
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_ATTACHED);//"Attached: \n";
// s += IntToString(Attached()->objectID);
// s += "\n";
}
else
{
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_NOT_ATTACHED);//"Not attached\n";
}
if (m_Visible == true)
{
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_VISIBLE);//"Visible\n";
}
else
{
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_NOT_VISIBLE);//"Not Visible\n";
}
if (Enabled() == true)
{
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_ENABLED);//"Enabled\n";
}
else
{
s += Application::GetInstance()->GetLocString(IDS_FLAGS_CPP_NOT_ENABLED);//"Not Enabled\n";
}
}
void
Flag::BecomeInteresting(bool render_me)
{
Check_Object(this);
LOAD_LOGIC("Become Interesting::Flag");
//
//------------------
// Validate children
//------------------
//
ChainIteratorOf<Entity*> children(&childEntityChain);
Entity *entity;
while ((entity = children.ReadAndNext()) != NULL)
{
Check_Object(entity);
entity->BecomeInteresting(render_me);
}
//
//-----------------------------
// Now make ourself interesting
//-----------------------------
//
/*
extern int g_TeamDecal;
if (GetTeam() != MWApplication::No_Team)
{
Team * team = MWApplication::GetInstance()->teams[GetTeam()]->GetCurrent();
if (team)
g_TeamDecal = team->GetTeamDecal();
}
*/
BaseClass::BecomeInteresting(render_me);
}
// MSL 5.03 Fixed Flag_Taken (disabled)
void Flag::Broadcast_FlagTaken(Adept::Entity& entity)
{
VehicleInterface* vi = VehicleInterface::GetInstance();
if (vi != 0)
{
if (&entity == vi->vehicle)
{
// m_LastFlagEvent = FLAG_TAKEN_BY_ME;
// MSL Currently only the server is playing the Taken_by_me sound. Disabling.
m_LastFlagEvent = FLAG_TAKEN;
}
else
{
m_LastFlagEvent = FLAG_TAKEN;
}
}
else
{
m_LastFlagEvent = FLAG_TAKEN;
}
ReactToFlagEvent(m_LastFlagEvent);
}
void Flag::PlaySound_FlagTaken()
{
if (VehicleInterface::GetInstance() != 0)
{
VehicleInterface::GetInstance()->ReactToEvent(VehicleInterface::FLAGTAKEN);
}
}
// MSL 5.03 Fixed Flag_Taken
void Flag::PlaySound_FlagTakenByMe()
{
if (VehicleInterface::GetInstance() != 0)
{
VehicleInterface::GetInstance()->ReactToEvent(VehicleInterface::YOUHAVEFLAG);
}
}
void Flag::Broadcast_FlagReturned()
{
m_LastFlagEvent = FLAG_RETURNED;
ReactToFlagEvent(m_LastFlagEvent);
}
void Flag::PlaySound_FlagReturned()
{
if (VehicleInterface::GetInstance() != 0)
{
VehicleInterface::GetInstance()->ReactToEvent(VehicleInterface::FLAGRETURNED);
}
}
void Flag::Broadcast_FlagCaptured()
{
m_LastFlagEvent = FLAG_CAPTURED;
ReactToFlagEvent(m_LastFlagEvent);
}
void Flag::PlaySound_FlagCaptured()
{
if (VehicleInterface::GetInstance() != 0)
{
MWMission *mission = Cast_Object (MWMission *,MWMission::GetInstance());
Check_Object (mission);
int theType = mission->GetMissionType();
if (theType == MWMission::MISSIONTYPE_COLISEUM)
{
VehicleInterface::GetInstance()->ReactToEvent(VehicleInterface::FLAGCAPTUREDHORN);
}
else
{
VehicleInterface::GetInstance()->ReactToEvent(VehicleInterface::FLAGCAPTUREDBUZZER);
}
}
}
void Flag::ReactToFlagEvent(FlagEvent event)
{
switch (event)
{
case FLAG_TAKEN:
{
Flag::PlaySound_FlagTaken();
break;
}
// MSL 5.03 Fixed Flag_Taken
case FLAG_TAKEN_BY_ME:
{
Flag::PlaySound_FlagTakenByMe();
break;
}
case FLAG_CAPTURED:
{
Flag::PlaySound_FlagCaptured();
break;
}
case FLAG_RETURNED:
{
Flag::PlaySound_FlagReturned();
break;
}
}
}
Flag::FlagEvent Flag::GetLastFlagEvent() const
{
return (m_LastFlagEvent);
}
void Flag::SetLastFlagEvent(FlagEvent event)
{
if ((event == m_LastFlagEvent) ||
(Network::GetInstance()->AmIServer()))
{
return;
}
ReactToFlagEvent(event);
m_LastFlagEvent = event;
}