diff --git a/main/source/mod/AvHBaseBuildable.cpp b/main/source/mod/AvHBaseBuildable.cpp index 8eb95ab8..6038ec20 100644 --- a/main/source/mod/AvHBaseBuildable.cpp +++ b/main/source/mod/AvHBaseBuildable.cpp @@ -89,7 +89,6 @@ #include "AvHPlayerUpgrade.h" #include "../dlls/animation.h" #include "AvHMovementUtil.h" -#include "AvHNetworkMessages.h" const int kBaseBuildableSpawnAnimation = 0; const int kBaseBuildableDeployAnimation = 1; @@ -703,25 +702,6 @@ AvHTeamNumber AvHBaseBuildable::GetTeamNumber() const void AvHBaseBuildable::Killed(entvars_t* pevAttacker, int iGib) { bool theInReset = GetGameRules()->GetIsGameInReset(); - - // Send a Cancel notification so any research can be removed from the research tracker. - if (GetGameRules()->GetGameStarted()) - { - FOR_ALL_ENTITIES(kAvHPlayerClassName, AvHPlayer*) - bool theShowNotification = false; - - // Show to friendlies... - if (theEntity->pev->team == this->pev->team) - { - theShowNotification = true; - } - - if (theShowNotification) - { - NetMsg_PlayHUDNotification(theEntity->pev, 1, MESSAGE_CANCEL, this->pev->origin.x, this->pev->origin.y); - } - END_FOR_ALL_ENTITIES(kAvHPlayerClassName); - } AvHBaseBuildable::SetHasBeenKilled(); GetGameRules()->RemoveEntityUnderAttack( this->entindex() ); diff --git a/main/source/mod/AvHHud.cpp b/main/source/mod/AvHHud.cpp index c70b02a7..1930507e 100644 --- a/main/source/mod/AvHHud.cpp +++ b/main/source/mod/AvHHud.cpp @@ -2578,6 +2578,7 @@ void AvHHud::ResetGame(bool inMapChanged) this->mLastTeamSpectated = TEAM_IND; this->mStructureNotificationList.clear(); + this->mResearchInfoList.clear(); this->mGameTime = -1; this->mTimeLimit = -1; @@ -2961,11 +2962,12 @@ int AvHHud::MsgFunc_ListPS(const char* pszName, int iSize, void* pbuf) BIND_MESSAGE(PlayHUDNot); int AvHHud::MsgFunc_PlayHUDNot(const char* pszName, int iSize, void* pbuf) { - int message_id, sound; + int flags, sound; float location_x, location_y; - NetMsg_PlayHUDNotification( pbuf, iSize, message_id, sound, location_x, location_y ); - - if(message_id == 0) + ResearchInfoListType researchInfoBuf; + NetMsg_PlayHUDNotification( pbuf, iSize, flags, sound, location_x, location_y , researchInfoBuf); + // Sound + if(flags == 0) { // Hack to avoid adding another network message (at max) if(!this->GetInTopDownMode()) @@ -3014,7 +3016,8 @@ int AvHHud::MsgFunc_PlayHUDNot(const char* pszName, int iSize, void* pbuf) this->PlayHUDSound((AvHHUDSound)sound); } - else + // Single HUD notification + else if (flags == 1) { // Push back icon HUDNotificationType theNotification; @@ -3027,6 +3030,12 @@ int AvHHud::MsgFunc_PlayHUDNot(const char* pszName, int iSize, void* pbuf) this->mStructureNotificationList.push_back(theNotification); } } + // Research info list + else + { + this->mResearchInfoList.clear(); + this->mResearchInfoList = researchInfoBuf; + } return 1; } @@ -5849,41 +5858,13 @@ void AvHHud::UpdateTooltips(float inCurrentTime) void AvHHud::UpdateStructureNotification(float inCurrentTime) { - const int kMaxIcons = 5; - Vector cancelLocation; + const int kMaxIcons = 4; + const float kTimeToDisplayIcon = 6.0f; AvHTeamNumber theCurrentTeam = this->GetHUDTeam(); - // Reset on a team change - if (this->mLastTeamNumber != theCurrentTeam) - this->mStructureNotificationList.clear(); - for(StructureHUDNotificationListType::iterator theIter = this->mStructureNotificationList.begin(); theIter != this->mStructureNotificationList.end(); /* no inc */) { - int theCost; - bool theResearchable; - float theBuildOrResearchTime; - AvHMessageID theTech = theIter->mStructureID; - this->mTechNodes.GetResearchInfo(theTech, theResearchable, theCost, theBuildOrResearchTime); - bool isResearch = AvHSHUGetIsResearchTech(theTech); - float timeToDisplayIcon = 6.0f; - - if (isResearch) - { - theIter->mResearchTimer = max(0, theBuildOrResearchTime - (inCurrentTime - theIter->mTime)); - timeToDisplayIcon = theBuildOrResearchTime; - } - else - { - theIter->mResearchTimer = 0; - } - - if (theTech == MESSAGE_CANCEL) - { - cancelLocation = theIter->mLocation; - this->mStructureNotificationList.erase(theIter); - theIter = this->mStructureNotificationList.begin(); - } - else if ((inCurrentTime > (theIter->mTime + timeToDisplayIcon)) || (!(theIter->mResearchTimer > 0) && this->mStructureNotificationList.size() > kMaxIcons ) || (theIter->mLocation == cancelLocation)) + if ((inCurrentTime > (theIter->mTime + kTimeToDisplayIcon)) || (this->mStructureNotificationList.size() > kMaxIcons)) { theIter = this->mStructureNotificationList.erase(theIter); } diff --git a/main/source/mod/AvHHud.h b/main/source/mod/AvHHud.h index 67edd580..5733822e 100644 --- a/main/source/mod/AvHHud.h +++ b/main/source/mod/AvHHud.h @@ -844,7 +844,6 @@ class AvHHud : public UIHud { AvHMessageID mStructureID; float mTime; - float mResearchTimer; int mPlayerIndex; Vector mLocation; } HUDNotificationType; @@ -852,6 +851,8 @@ class AvHHud : public UIHud typedef vector< HUDNotificationType > StructureHUDNotificationListType; StructureHUDNotificationListType mStructureNotificationList; + ResearchInfoListType mResearchInfoList; + int mCrosshairShowCount; AVHHSPRITE mCrosshairSprite; wrect_t mCrosshairRect; diff --git a/main/source/mod/AvHHudRender.cpp b/main/source/mod/AvHHudRender.cpp index 2ee56ce4..64f1a2c5 100644 --- a/main/source/mod/AvHHudRender.cpp +++ b/main/source/mod/AvHHudRender.cpp @@ -1474,64 +1474,69 @@ void AvHHud::DrawHUDStructureNotification() float theCurrentX = kHUDStructureNotificationStartX; float theCurrentY = kHUDStructureNotificationStartY; - //bool inTopDown = GetInTopDownMode(); - AvHTeamNumber theCurrentTeam = this->GetHUDTeam(); + bool isMarine = GetIsMarine(); float kSmallScaleFactor; //Don't make building icons smaller if alien. - (theCurrentTeam == TEAM_TWO) ? kSmallScaleFactor = 1.0f : kSmallScaleFactor = 0.75f; + (isMarine) ? kSmallScaleFactor = 0.75f : kSmallScaleFactor = 1.0f; const float kIconWidthSmall = kHUDStructureNotificationIconWidth * kSmallScaleFactor; const float kIconHeightSmall = kHUDStructureNotificationIconHeight * kSmallScaleFactor; + + if (isMarine) + { + for (ResearchInfoListType::iterator theIter = this->mResearchInfoList.begin(); theIter != this->mResearchInfoList.end(); theIter++) + { + // Draw icon + AvHMessageID theIconTech = theIter->mResearch; + int theFrame = 0; + int theStartX = (theCurrentX + kHUDStructureNotificationIconWidth + kHUDStructureNotificationIconHorizontalSpacing)*ScreenWidth(); + + string theResearchTimerText; + ActionButton::GetLabelForMessage(theIconTech, theResearchTimerText); + + int timeLeft = theIter->mTimeResearchDone - this->mTimeOfCurrentUpdate; + int theMinutesLeft = timeLeft / 60; + int theSecondsLeft = timeLeft % 60; + + if (theMinutesLeft) + theResearchTimerText += " - " + MakeStringFromInt(theMinutesLeft) + "m " + MakeStringFromInt(theSecondsLeft) + "s"; + else + theResearchTimerText += " - " + MakeStringFromInt(theSecondsLeft) + "s"; + + int theR, theG, theB; + this->GetPrimaryHudColor(theR, theG, theB, true, false); + char theCharBuffer[512]; + sprintf(theCharBuffer, "%s", theResearchTimerText.c_str()); + + float theCurrentTextY = theCurrentY + (kHUDStructureNotificationIconHeight * kTextHeightCenteringFactor); + + this->DrawTechTreeSprite(theIconTech, theCurrentX*ScreenWidth(), theCurrentY*ScreenHeight(), kHUDStructureNotificationIconWidth*ScreenWidth(), kHUDStructureNotificationIconHeight*ScreenHeight(), theFrame); + this->DrawHudString(theStartX, theCurrentTextY*ScreenHeight(), ScreenWidth(), theCharBuffer, theR, theG, theB); + + theCurrentY += (kHUDStructureNotificationIconHeight + kHUDStructureNotificationIconVerticalSpacing); + } + } for(StructureHUDNotificationListType::iterator theIter = this->mStructureNotificationList.begin(); theIter != this->mStructureNotificationList.end(); theIter++) { // Draw icon AvHMessageID theIconTech = theIter->mStructureID; int theFrame = 0; - string theLocationName = this->GetNameOfLocation(theIter->mLocation); int theStartX = (theCurrentX + kHUDStructureNotificationIconWidth + kHUDStructureNotificationIconHorizontalSpacing)*ScreenWidth(); bool isResearch = AvHSHUGetIsResearchTech(theIconTech); - //Don't draw cancel notifications. Still getting sent them in UpdateStructureNotification so they can be read to remove research. - if (theIconTech != MESSAGE_CANCEL) + if (!isResearch) { - if (isResearch) + this->DrawTechTreeSprite(theIconTech, theCurrentX*ScreenWidth(), theCurrentY*ScreenHeight(), kIconWidthSmall*ScreenWidth(), kIconHeightSmall*ScreenHeight(), theFrame); + if (theLocationName != "") { - string theResearchTimerText; - ActionButton::GetLabelForMessage(theIter->mStructureID, theResearchTimerText); - - int timeLeft = theIter->mResearchTimer; - int theMinutesLeft = timeLeft / 60; - int theSecondsLeft = timeLeft % 60; - - if (theMinutesLeft) - theResearchTimerText += " - " + MakeStringFromInt(theMinutesLeft) + "m " + MakeStringFromInt(theSecondsLeft) + "s"; - else - theResearchTimerText += " - " + MakeStringFromInt(theSecondsLeft) + "s"; - - int theR, theG, theB; - this->GetPrimaryHudColor(theR, theG, theB, true, false); - char theCharBuffer[512]; - sprintf(theCharBuffer, "%s", theResearchTimerText.c_str()); - - float theCurrentTextY = theCurrentY + (kHUDStructureNotificationIconHeight * kTextHeightCenteringFactor); - - this->DrawTechTreeSprite(theIconTech, theCurrentX*ScreenWidth(), theCurrentY*ScreenHeight(), kHUDStructureNotificationIconWidth*ScreenWidth(), kHUDStructureNotificationIconHeight*ScreenHeight(), theFrame); - this->DrawHudString(theStartX, theCurrentTextY*ScreenHeight(), ScreenWidth(), theCharBuffer, theR, theG, theB); - } - else - { - this->DrawTechTreeSprite(theIconTech, theCurrentX*ScreenWidth(), theCurrentY*ScreenHeight(), kIconWidthSmall*ScreenWidth(), kIconHeightSmall*ScreenHeight(), theFrame); - int theStartXsmall = theStartX * kSmallScaleFactor; float theCurrentTextY = theCurrentY + (kIconHeightSmall * kTextHeightCenteringFactor); - - if (theLocationName != "") - this->DrawTranslatedString(theStartXsmall, theCurrentTextY*ScreenHeight(), theLocationName.c_str(), false, true); + this->DrawTranslatedString(theStartXsmall, theCurrentTextY*ScreenHeight(), theLocationName.c_str(), false, true); } // Increment coords - theCurrentY += (kHUDStructureNotificationIconHeight + kHUDStructureNotificationIconVerticalSpacing); + theCurrentY += (kIconHeightSmall + kHUDStructureNotificationIconVerticalSpacing); } } @@ -4229,6 +4234,22 @@ void AvHHud::RenderAlienUI() { theR = theG = theB = 100; } + // If building, draw time until completion. + else if (theIter->mStatus > 0 && theIter->mStatus < 6) + { + const int totalBuildTime = BALANCE_VAR(kHiveBuildTime); + if (theIter->mBuildTime > 0 && theIter->mBuildTime < totalBuildTime) + { + int timeLeft = theIter->mBuildTime; + int theMinutesLeft = timeLeft / 60; + int theSecondsLeft = timeLeft % 60; + + if (theMinutesLeft) + theTranslatedLocationName = MakeStringFromInt(theMinutesLeft) + "m " + MakeStringFromInt(theSecondsLeft) + "s - " + theTranslatedLocationName; + else + theTranslatedLocationName = MakeStringFromInt(theSecondsLeft) + "s - " + theTranslatedLocationName; + } + } this->DrawHudStringReverse(mViewport[0] + mViewport[2] - 5, theScreenPosY, ScreenWidth(), (char*)theTranslatedLocationName.c_str(), theR, theG, theB); } diff --git a/main/source/mod/AvHNetworkMessages.cpp b/main/source/mod/AvHNetworkMessages.cpp index 83ea9f4b..bef4c595 100644 --- a/main/source/mod/AvHNetworkMessages.cpp +++ b/main/source/mod/AvHNetworkMessages.cpp @@ -73,7 +73,7 @@ void Net_InitializeMessages(void) g_msgFog = REG_USER_MSG( "Fog", -1 ); g_msgGameStatus = REG_USER_MSG( "GameStatus", -1 ); g_msgListPS = REG_USER_MSG( "ListPS", -1 ); - g_msgPlayHUDNotification = REG_USER_MSG( "PlayHUDNot", 6 ); + g_msgPlayHUDNotification = REG_USER_MSG( "PlayHUDNot", -1 ); g_msgHUDSetUpgrades = REG_USER_MSG( "SetUpgrades", 1); g_msgProgressBar = REG_USER_MSG( "Progress", -1 ); g_msgServerVar = REG_USER_MSG( "ServerVar", -1 ); @@ -969,6 +969,7 @@ enum AlienInfo_ChangeFlags if( changes & HEALTH_CHANGED ) { hives[counter].mHealthPercentage = READ_BYTE(); + hives[counter].mBuildTime = READ_BYTE(); } } } @@ -1019,8 +1020,9 @@ enum AlienInfo_ChangeFlags client_hives[index].mUnderAttack != current->mUnderAttack || client_hives[index].mTechnology != current->mTechnology ) { change_flags |= STATUS_CHANGED; } - if( client_hives.size() <= index || client_hives[index].mHealthPercentage != current->mHealthPercentage ) + if( client_hives.size() <= index || client_hives[index].mHealthPercentage != current->mHealthPercentage || client_hives[index].mBuildTime != current->mBuildTime ) { change_flags |= HEALTH_CHANGED; } + WRITE_BYTE(change_flags); //send change data @@ -1048,6 +1050,7 @@ enum AlienInfo_ChangeFlags if( change_flags & HEALTH_CHANGED ) { WRITE_BYTE(current->mHealthPercentage); + WRITE_BYTE(current->mBuildTime); } } MESSAGE_END(); @@ -1494,17 +1497,43 @@ union float_converter #endif #ifndef AVH_SERVER - void NetMsg_PlayHUDNotification( void* const buffer, const int size, int& flags, int& sound, float& location_x, float& location_y ) + void NetMsg_PlayHUDNotification( void* const buffer, const int size, int& flags, int& sound, float& location_x, float& location_y, ResearchInfoListType& researching) { BEGIN_READ( buffer, size ); flags = READ_BYTE(); - sound = READ_BYTE(); - location_x = READ_COORD(); - location_y = READ_COORD(); + // If sound or one time build notification + if (flags == 0 || flags == 1) + { + sound = READ_BYTE(); + location_x = READ_COORD(); + location_y = READ_COORD(); + } + else + { + // Research tracker info + if (flags == 2) + { + int num_research = READ_BYTE(); + researching.clear(); + for (int counter = 0; counter < num_research; counter++) + { + AvHResearchInfo theResearchInfoEntry; + theResearchInfoEntry.mResearch = (AvHMessageID)READ_BYTE(); + + float_converter c; + c.l = READ_LONG(); + theResearchInfoEntry.mTimeResearchDone = c.f; + + //theResearchInfoEntry.mEntityIndex = READ_LONG(); + + researching.push_back(theResearchInfoEntry); + } + } + } END_READ(); } #else - void NetMsg_PlayHUDNotification( entvars_t* const pev, const int flags, const int sound, const float location_x, const float location_y ) + void NetMsg_PlayHUDNotification_Single(entvars_t* const pev, const int flags, const int sound, const float location_x, const float location_y) { MESSAGE_BEGIN( MSG_ONE, g_msgPlayHUDNotification, NULL, pev ); WRITE_BYTE( flags ); @@ -1513,6 +1542,28 @@ union float_converter WRITE_COORD( location_y ); MESSAGE_END(); } + void NetMsg_PlayHUDNotification_Research(entvars_t* const pev, const int flags, const ResearchInfoListType& researching) + { + MESSAGE_BEGIN(MSG_ONE, g_msgPlayHUDNotification, NULL, pev); + WRITE_BYTE(flags); + if (flags == 2) + { + // Research tracker info + WRITE_BYTE(researching.size()); + ResearchInfoListType::const_iterator current, end = researching.end(); + for (current = researching.begin(); current != end; ++current) + { + WRITE_BYTE(current->mResearch); + + float_converter c; + c.f = current->mTimeResearchDone; + WRITE_LONG(c.l); + + //WRITE_LONG(current->mEntityIndex); + } + } + MESSAGE_END(); + } #endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/main/source/mod/AvHNetworkMessages.h b/main/source/mod/AvHNetworkMessages.h index 7488410c..24e285e3 100644 --- a/main/source/mod/AvHNetworkMessages.h +++ b/main/source/mod/AvHNetworkMessages.h @@ -92,7 +92,8 @@ void NetMsg_ListPS( entvars_t* const pev, const string& system_name ); void NetMsg_HUDSetUpgrades( int upgradeMask ); void NetMsg_HUDSetUpgrades( entvars_t* const pev, int upgradeMask ); - void NetMsg_PlayHUDNotification( entvars_t* const pev, const int flags, const int sound, const float location_x, const float location_y ); + void NetMsg_PlayHUDNotification_Single( entvars_t* const pev, const int flags, const int sound, const float location_x, const float location_y); + void NetMsg_PlayHUDNotification_Research(entvars_t* const pev, const int flags, const ResearchInfoListType& researching); void NetMsg_ProgressBar( entvars_t* const pev, const int entity_number, const int progress, int percent=0 ); void NetMsg_ServerVar( entvars_t* const pev, const string& name, const int& value ); void NetMsg_SetGammaRamp( entvars_t* const pev, const float gamma ); @@ -184,7 +185,7 @@ void NetMsg_GameStatus( void* const buffer, const int size, int& status_code, AvHMapMode& map_mode, int& game_time, int& timelimit, int& misc_data ); void NetMsg_ListPS( void* const buffer, const int size, string& system_name ); void NetMsg_HUDSetUpgrades( void* const buffer, const int size, int& upgradeMask ); - void NetMsg_PlayHUDNotification( void* const buffer, const int size, int& flags, int& sound, float& location_x, float& location_y ); + void NetMsg_PlayHUDNotification( void* const buffer, const int size, int& flags, int& sound, float& location_x, float& location_y, ResearchInfoListType& researching); void NetMsg_ProgressBar( void* const buffer, const int size, int& entity_number, int& progress, int &percent); //45 void NetMsg_ServerVar( void* const buffer, const int size, string& name, int& value ); diff --git a/main/source/mod/AvHPlayer.cpp b/main/source/mod/AvHPlayer.cpp index 88f8494e..17b14c24 100644 --- a/main/source/mod/AvHPlayer.cpp +++ b/main/source/mod/AvHPlayer.cpp @@ -3483,6 +3483,7 @@ void AvHPlayer::Init() // Clear out hive info this->mClientHiveInfo.clear(); + this->mClientResearchInfo.clear(); this->mClientGamma = kDefaultMapGamma; @@ -4944,7 +4945,7 @@ bool AvHPlayer::PlayHUDSound(AvHHUDSound inSound, float x, float y) const if((inSound > HUD_SOUND_INVALID) && (inSound < HUD_SOUND_MAX)) { - NetMsg_PlayHUDNotification( this->pev, 0, inSound, x, y ); + NetMsg_PlayHUDNotification_Single( this->pev, 0, inSound, x, y ); theSuccess = true; } @@ -4958,25 +4959,25 @@ void AvHPlayer::PlayHUDStructureNotification(AvHMessageID inMessageID, const Vec // This player built a structure. Tell all his teammates FOR_ALL_ENTITIES(kAvHPlayerClassName, AvHPlayer*) - //if(theEntity->GetIsRelevant() && !theEntity->GetIsBeingDigested()) - //{ + if(theEntity->GetIsRelevant() && !theEntity->GetIsBeingDigested()) + { // Don't send our own messages to ourself unless cheats are enabled - //if(GetGameRules()->GetCheatsEnabled() || (this != theEntity)) - //{ - bool theShowNotification = false; + if(GetGameRules()->GetCheatsEnabled() || (this != theEntity)) + { + bool theShowNotification = false; - // Show to friendlies... - if(theEntity->pev->team == this->pev->team) - { - theShowNotification = true; - } - - if(theShowNotification) - { - NetMsg_PlayHUDNotification( theEntity->pev, 1, inMessageID, inLocation.x, inLocation.y ); - } - // } - //} + // Show to friendlies... + if(theEntity->pev->team == this->pev->team) + { + theShowNotification = true; + } + + if(theShowNotification) + { + NetMsg_PlayHUDNotification_Single(theEntity->pev, 1, inMessageID, inLocation.x, inLocation.y); + } + } + } END_FOR_ALL_ENTITIES(kAvHPlayerClassName); } } @@ -5354,8 +5355,6 @@ void AvHPlayer::Research(AvHMessageID inUpgrade, int inEntityIndex) theRefund = min(theRefund, (float)theResearchCost); this->SetResources(this->GetResources() + theRefund); } - //Tell team about cancel so it can update research notifications - this->PlayHUDStructureNotification(inUpgrade, theEntity->pev->origin); char* theResearchName = NULL; if(AvHSHUGetResearchTechName(inUpgrade, theResearchName)) @@ -9497,38 +9496,48 @@ void AvHPlayer::UpdateMarineUI() bool theIsMarine = false; bool theIsAlien = false; - if(this->GetIsAlien()) - { + if(this->GetIsAlien()) + { return; - } + } int tmpUpgrades=0; - for(int i = 0; i < MAX_ITEM_TYPES; i++) - { + for(int i = 0; i < MAX_ITEM_TYPES; i++) + { AvHBasePlayerWeapon* theActiveWeapon = dynamic_cast(this->m_rgpPlayerItems[i]); - while(theActiveWeapon) - { + while(theActiveWeapon) + { ItemInfo ii; theActiveWeapon->GetItemInfo(&ii); switch ( ii.iId ) { - case AVH_WEAPON_WELDER: - tmpUpgrades |= 0x1; - break; - case AVH_WEAPON_MINE: - tmpUpgrades |= 0x2; - break; - case AVH_WEAPON_GRENADE: - tmpUpgrades |= 0x4; - break; + case AVH_WEAPON_WELDER: + tmpUpgrades |= 0x1; + break; + case AVH_WEAPON_MINE: + tmpUpgrades |= 0x2; + break; + case AVH_WEAPON_GRENADE: + tmpUpgrades |= 0x4; + break; } - // Next weapon - theActiveWeapon = dynamic_cast(theActiveWeapon->m_pNext); - } - } + // Next weapon + theActiveWeapon = dynamic_cast(theActiveWeapon->m_pNext); + } + } if ( tmpUpgrades != this->mMarineHUDUpgrades ) { NetMsg_HUDSetUpgrades(this->pev, tmpUpgrades&0x7); this->mMarineHUDUpgrades=tmpUpgrades; } + + if (theTeamPointer) + { + ResearchInfoListType theTeamResearchInfo = theTeamPointer->GetResearchInfoList(); + if (this->mClientResearchInfo != theTeamResearchInfo) + { + NetMsg_PlayHUDNotification_Research(this->pev, 2, theTeamResearchInfo); + this->mClientResearchInfo = theTeamResearchInfo; + } + } } // TODO: Send only changed blips, send only the changes for each blip. diff --git a/main/source/mod/AvHPlayer.h b/main/source/mod/AvHPlayer.h index 7e6ab419..bcf2e7e9 100644 --- a/main/source/mod/AvHPlayer.h +++ b/main/source/mod/AvHPlayer.h @@ -781,7 +781,8 @@ class AvHPlayer : public CBasePlayer, public AvHCloakable, public BalanceChangeL AvHBaseInfoLocationListType mClientInfoLocations; - HiveInfoListType mClientHiveInfo; + HiveInfoListType mClientHiveInfo; + ResearchInfoListType mClientResearchInfo; AvHAlienUpgradeListType mClientUpgrades; diff --git a/main/source/mod/AvHResearchManager.cpp b/main/source/mod/AvHResearchManager.cpp index 61917a22..b8833bff 100644 --- a/main/source/mod/AvHResearchManager.cpp +++ b/main/source/mod/AvHResearchManager.cpp @@ -166,6 +166,11 @@ bool AvHResearchManager::GetResearchInfo(AvHMessageID inTech, bool& outIsResearc return theFoundIt; } +ResearchListType& AvHResearchManager::GetResearchingTech() +{ + return this->mResearchingTech; +} + const AvHTechTree& AvHResearchManager::GetTechNodes() const { return this->mTechNodes; diff --git a/main/source/mod/AvHResearchManager.h b/main/source/mod/AvHResearchManager.h index 0bfa09ed..f0e26fbb 100644 --- a/main/source/mod/AvHResearchManager.h +++ b/main/source/mod/AvHResearchManager.h @@ -57,6 +57,8 @@ class AvHResearchManager bool GetResearchInfo(AvHMessageID inTech, bool& outIsResearchable, int& outCost, float& outTime) const; + ResearchListType& GetResearchingTech(); + void TriggerAddTech(AvHTechID inTechID); void TriggerRemoveTech(AvHTechID inTechID); diff --git a/main/source/mod/AvHSharedTypes.h b/main/source/mod/AvHSharedTypes.h index 489139f9..99d41975 100644 --- a/main/source/mod/AvHSharedTypes.h +++ b/main/source/mod/AvHSharedTypes.h @@ -19,7 +19,7 @@ class AvHHiveInfo { bool theAreEqual = CHECK_EQUAL(mHealthPercentage) && CHECK_EQUAL(mPosX) && CHECK_EQUAL(mPosY) && CHECK_EQUAL(mPosZ) && CHECK_EQUAL(mStatus) - && CHECK_EQUAL(mUnderAttack) && CHECK_EQUAL(mTechnology); + && CHECK_EQUAL(mUnderAttack) && CHECK_EQUAL(mTechnology) && CHECK_EQUAL(mBuildTime); return theAreEqual; } @@ -35,12 +35,44 @@ class AvHHiveInfo int mStatus; bool mUnderAttack; int mTechnology; - + int mBuildTime; int mHealthPercentage; }; #undef CHECK_EQUAL typedef vector HiveInfoListType; + + +#define CHECK_EQUAL(x) (this->x == inResearchInfo.x ) +class AvHResearchInfo +{ +public: + bool operator==(const AvHResearchInfo& inResearchInfo) const + { + bool theAreEqual = CHECK_EQUAL(mResearch) && CHECK_EQUAL(mTimeResearchDone)/* && CHECK_EQUAL(mEntityIndex)*/; + return theAreEqual; + } + + bool operator!=(const AvHResearchInfo& inResearchInfo) const + { + return !operator==(inResearchInfo); + } + + //float mPosX; + //float mPosY; + //float mPosZ; + + AvHMessageID mResearch; + float mTimeResearchDone; + //int mEntityIndex; + + +}; +#undef CHECK_EQUAL + +typedef vector ResearchInfoListType; + + typedef int EntityInfo; typedef vector EntityListType; diff --git a/main/source/mod/AvHTeam.cpp b/main/source/mod/AvHTeam.cpp index fa1b1b18..34e032a9 100644 --- a/main/source/mod/AvHTeam.cpp +++ b/main/source/mod/AvHTeam.cpp @@ -428,6 +428,10 @@ HiveInfoListType AvHTeam::GetHiveInfoList() const return this->mHiveInfoList; } +ResearchInfoListType AvHTeam::GetResearchInfoList() const +{ + return this->mResearchInfoList; +} const AvHResearchManager& AvHTeam::GetResearchManager() const { @@ -860,6 +864,7 @@ void AvHTeam::ResetGame() //this->InitializeRandomResourceShares(); this->mHiveInfoList.clear(); + this->mResearchInfoList.clear(); this->mTimeOfLastStructureUpdate = -1; this->mVoteStarted = false; @@ -1570,11 +1575,13 @@ void AvHTeam::UpdateTeamStructures() // Fill in hive status int theStatus = kHiveInfoStatusBuilt; + int theBuildTime; // Unbuilt hives if(theEntity->pev->team == 0) { theStatus = kHiveInfoStatusUnbuilt; + theBuildTime = 0; } // building hives else if(!theEntity->GetIsBuilt()) @@ -1585,15 +1592,20 @@ void AvHTeam::UpdateTeamStructures() theStatus = kHiveInfoStatusBuildingStage1; int theSteps = (int)(theNormalizedBuildPercentage*5.0f); theStatus += theSteps; + + int totalBuildTime = BALANCE_VAR(kHiveBuildTime); + theBuildTime = totalBuildTime - (theNormalizedBuildPercentage * totalBuildTime); } else { theStatus = kHiveInfoStatusUnbuilt; + theBuildTime = 0; } } theHiveInfo.mStatus = theStatus; theHiveInfo.mTechnology = (int)(theEntity->GetTechnology()); + theHiveInfo.mBuildTime = theBuildTime; // Under attack? theHiveInfo.mUnderAttack = GetGameRules()->GetIsEntityUnderAttack(theEntityIndex); @@ -1632,6 +1644,22 @@ void AvHTeam::UpdateTeamStructures() } END_FOR_ALL_ENTITIES(kwsTeamCommand); this->mNumBuiltCommandStations = theNumActiveCommandStations; + + // Research info to send to clients for research tracker + this->mResearchInfoList.clear(); + ResearchListType researchingTech = this->mResearchManager.GetResearchingTech(); + + for (ResearchListType::iterator theIter = researchingTech.begin(); theIter != researchingTech.end(); theIter++) + { + AvHResearchInfo theResearchInfo; + + + theResearchInfo.mResearch = theIter->GetResearching(); + theResearchInfo.mTimeResearchDone = theIter->GetTimeResearchDone(); + //theResearchInfo.mEntityIndex = theIter->GetEntityIndex(); + + this->mResearchInfoList.push_back(theResearchInfo); + } } } } diff --git a/main/source/mod/AvHTeam.h b/main/source/mod/AvHTeam.h index c5c8a2b8..ce90d411 100644 --- a/main/source/mod/AvHTeam.h +++ b/main/source/mod/AvHTeam.h @@ -161,7 +161,8 @@ class AvHTeam void ResetGame(); virtual void SetGameStarted(bool inGameStarted); - HiveInfoListType GetHiveInfoList() const; + HiveInfoListType GetHiveInfoList() const; + ResearchInfoListType GetResearchInfoList() const; // Tech nodes for team void InitializeTechNodes(); @@ -299,8 +300,9 @@ class AvHTeam typedef map AvHServerPlayerDataListType; AvHServerPlayerDataListType mServerPlayerData; - HiveInfoListType mHiveInfoList; - float mTimeOfLastStructureUpdate; + HiveInfoListType mHiveInfoList; + ResearchInfoListType mResearchInfoList; + float mTimeOfLastStructureUpdate; EntityListType mLowResourceAlerts; float mTimeLastHintUpdate;