#include "rp.h" #pragma hdrstop #include "crusher.h" #include "..\munga\dropzone.h" #include "vtv.h" #include "..\munga\hostmgr.h" #include "..\munga\app.h" #include "scorzone.h" #include "..\munga\nttmgr.h" //############################################################################# //############################### Crusher ############################## //############################################################################# //############################################################################# // Shared Data Support // Derivation* Crusher::GetClassDerivations() { static Derivation classDerivations(RPPlayer::GetClassDerivations(), "Crusher"); return &classDerivations; } Crusher::SharedData Crusher::DefaultData( Crusher::GetClassDerivations(), Crusher::GetMessageHandlers(), Crusher::GetAttributeIndex(), Crusher::StateCount, (Crusher::MakeHandler)Crusher::Make ); const Receiver::HandlerEntry Crusher::MessageHandlerEntries[]= { MESSAGE_ENTRY(Crusher, Score), MESSAGE_ENTRY(Crusher, DropZoneReply), MESSAGE_ENTRY(Crusher, ScoreZoneReply) }; Receiver::MessageHandlerSet& Crusher::GetMessageHandlers() { static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(Crusher::MessageHandlerEntries), Crusher::MessageHandlerEntries, RPPlayer::GetMessageHandlers()); return messageHandlers; } //############################################################################# // Message Support // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Crusher::DropZoneReplyMessageHandler( DropZone::ReplyMessage *message ) { Check(this); Check(message); if (!playerVehicle) { CreatePlayerVehicle(message->dropZoneLocation); InitializePlayerLink(); SetPerformance(&Crusher::PlayerSimulation); AlwaysExecute(); deathCount = 0; } else if (deathCount == message->deathCount) { if (GetSimulationState() == MissionEndingState) { Check_Fpu(); return; } if (GetSimulationState() != DropZoneAcquiredState) { ResetAfterDeath(message); Check_Fpu(); return; } } else { Check_Fpu(); return; } DeleteAllOffensivePlayers(); ForceUpdate(); SetSimulationState(VehicleTranslocatedState); VTV *vtv = (VTV*)playerVehicle; Check(vtv); vtv->Reset(message->dropZoneLocation, True); if (goalEntity) { Check(goalEntity); PointVTVTowardGoal(); vtv->ForceUpdate(); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Crusher::AddOffensivePlayer(OffensivePlayer &offensive_player) { Check(this); Check(offensive_player.offensivePlayer); RPPlayer *rp_player = offensive_player.offensivePlayer; // //--------------------------------------------- // Damage & Death Points awarded if .... // This Crusher gets hit by a runner or a Blocker // from the other team with collision Damage! //--------------------------------------------- // if ( ( rp_player->playerType == BlockerPlayerType || rp_player->playerType == RunnerPlayerType ) && teamID != rp_player->teamID && offensive_player.damageType == Damage::CollisionDamageType ) { offensive_player.deathBonus = 500.0f; } else { offensive_player.deathBonus = 0.0f; } offensivePlayerList.AddValue( &offensive_player, offensive_player.damageType ); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Crusher::ScoreMessageHandler(ScoreMessage *message) { Check(this); Check(message); Check(application); RPPlayer::ScoreMessageHandler(message); HostManager *host = application->GetHostManager(); Check(host); RPPlayer *rp_player = (RPPlayer*) host->GetEntityPointer(message->pointSender); if (!rp_player) { Check_Fpu(); return; } Check(rp_player); if ( rp_player->playerType == RunnerPlayerType && rp_player->teamID != teamID ) { Scalar score_award = message->scoreAward * 2.0f; // //------------------------------------------------------ // Create the score award and pass it on to the runner //------------------------------------------------------ // ScoreMessage score_message( RPPlayer::ScoreMessageID, sizeof(RPPlayer::ScoreMessage), CrusherScorePointType, score_award, GetEntityID() ); if (teamRunner) { Check(teamRunner); teamRunner->Dispatch(&score_message); } } // // HACK - ECH 7/6/95 - Allow the player vehicle to respond to score // messages, allows attribute system to be used for scoring // Check(playerVehicle); playerVehicle->RespondToScoreMessage(message); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Crusher::ScoreZoneReplyMessageHandler( ScoreZone::ReplyMessage *//message ) { //empty } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Crusher::PlayerSimulation(Scalar time_slice) { Check(this); // //------------------------------------------------------------------------ // Service the status message queue //------------------------------------------------------------------------ // StatusMessageUpdate(time_slice); // //----------------------------------- // Find the runners if we haven't yet //----------------------------------- // Player::PlayerSimulation(time_slice); InitTeamRunner(); // //-------------------------------------------------------------------------- // If we know who the enemy is, but not what his vehicle is, try to find the // vehicle //-------------------------------------------------------------------------- // if (enemyRunner) { Entity *our_vehicle = GetPlayerVehicle(); Check(our_vehicle); if (!goalEntity) { goalEntity = enemyRunner->GetPlayerVehicle(); if (goalEntity) { PointVTVTowardGoal(); our_vehicle->ForceUpdate(); } } // //---------------------------------------------------------------------- // Otherwise, if we aren't running yet, make sure that we are pointed in // the correct direction - HACK //---------------------------------------------------------------------- // else if ( application->GetApplicationState() < Application::RunningMission ) { Scalar alignment = our_vehicle->localToWorld(2,2); PointVTVTowardGoal(); if (alignment * goalEntity->localToWorld(2,2) < 0.0f) { our_vehicle->ForceUpdate(); } } // //---------------------------------------------- // If the game is running, set the goal properly //---------------------------------------------- // else { goalEntity = enemyRunner->GetPlayerVehicle(); } } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Crusher::PointVTVTowardGoal() { Check(this); Vector3D to_goal(Vector3D::Identity); if (goalEntity) { // //------------------------------ // Find the distance to the goal //------------------------------ // to_goal.Subtract( goalEntity->localOrigin.linearPosition, playerVehicle->localOrigin.linearPosition ); Scalar length_to_goal; length_to_goal = to_goal.LengthSquared(); // //---------------------------- // Less than 100 meters away? //---------------------------- // if (length_to_goal < 10000.0f) { // //----------------------------------------------- // The goalEntity is in front of us so point in // the same direction as the goalEntity //----------------------------------------------- // playerVehicle->localOrigin.angularPosition.x = 0.0f; playerVehicle->localOrigin.angularPosition.z = 0.0f; if (goalEntity->localToWorld(2,2) >= 0.0f) { playerVehicle->localOrigin.angularPosition.y = 0.0f; playerVehicle->localOrigin.angularPosition.w = 1.0f; } else { playerVehicle->localOrigin.angularPosition.y = 1.0f; playerVehicle->localOrigin.angularPosition.w = 0.0f; } } else { // //--------------------------------- // Point toward the goal Entity // disregard and Y direction //--------------------------------- // playerVehicle->localOrigin.angularPosition.x = 0.0f; playerVehicle->localOrigin.angularPosition.z = 0.0f; // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // is the goal in front or behind me //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // if (to_goal.z <= 0.0f) { playerVehicle->localOrigin.angularPosition.y = 0.0f; playerVehicle->localOrigin.angularPosition.w = 1.0f; } else { playerVehicle->localOrigin.angularPosition.y = 1.0f; playerVehicle->localOrigin.angularPosition.w = 0.0f; } } playerVehicle->localToWorld = playerVehicle->localOrigin; } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Crusher::Crusher( MakeMessage *creation_message, SharedData &shared_data ) : RPPlayer(creation_message, shared_data) { StatusMessage *message = new StatusMessage(NULL,RPStatusMessage::CrusherMessage,1e10); Register_Object(message); AddStatusMessage(message); teamRunner = NULL; enemyRunner = NULL; Check_Fpu(); } Crusher::~Crusher() { Check(this); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Crusher* Crusher::Make(MakeMessage *creation_message) { Check_Fpu(); return new Crusher(creation_message); } //############################################################################# // void Crusher::InitTeamRunner() { Check(this); Check(application); EntityManager *entity_mgr = application->GetEntityManager(); Check(entity_mgr); EntityGroup *runner_group = entity_mgr->FindGroup("RunnerPlayers"); if(runner_group) { Check(runner_group); ChainIteratorOf iterator(runner_group->groupMembers); RPPlayer *runner; int winning_rank = 10000; while ((runner = (RPPlayer*) iterator.ReadAndNext()) != NULL) { Check(runner); if (runner->teamID == teamID) { teamRunner = runner; } else { if (runner->playerRanking < winning_rank) { enemyRunner = runner; winning_rank = runner->playerRanking; } } } } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical Crusher::TestInstance() const { return IsDerivedFrom(*GetClassDerivations()); }