314 lines
12 KiB
C++
Executable File
314 lines
12 KiB
C++
Executable File
/**
|
|
* Handler for player data
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by hjl, SLSE, 2017-02-20
|
|
*/
|
|
|
|
#include "handler_participant_building.h"
|
|
#include <CentralEffectSimulation/handler_participant.h>
|
|
#include <ProjectDataManagement/pdm_dtc.h>
|
|
|
|
#define PERCENT_100 100
|
|
|
|
namespace CesParticipantBuildings
|
|
{
|
|
|
|
HandlerParticipantBuilding::HandlerParticipantBuilding(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
|
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
|
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &handlerBuildingData,
|
|
QObject *parent)
|
|
: QObject(parent)
|
|
, m_ddsHandler(ddsHandler)
|
|
, m_handlerParticipant(participantHandler)
|
|
, m_handlerBuildingData(handlerBuildingData)
|
|
, m_buildingStates()
|
|
, m_requestMap()
|
|
, m_timer(new QTimer(this))
|
|
, m_logger(CentralEffectSimulation::getLogger("Plugin.ParticipantBuildings.HandlerParticipantBuilding"))
|
|
{
|
|
m_timer->setSingleShot(true);
|
|
connect(m_timer, &QTimer::timeout, this, &HandlerParticipantBuilding::sendFtcCesHitRequestTimeout);
|
|
|
|
} // end of ctor()
|
|
//-----------------------------------------------------------------------------
|
|
|
|
HandlerParticipantBuilding::~HandlerParticipantBuilding()
|
|
{
|
|
} // end of dtor()
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool HandlerParticipantBuilding::init()
|
|
{
|
|
auto dtcBld = m_ddsHandler->dtcBld();
|
|
dtcBld->waitForHistoricalDataBuildingState(1000);
|
|
|
|
connect(dtcBld.get(), &Buildings::Interface::Dtc::buildingStateChanged,
|
|
this, &HandlerParticipantBuilding::onBuildingStateChanged);
|
|
|
|
// Get 'static' data for all buildingStates
|
|
{
|
|
auto cb = [this](const Buildings::BuildingState & bs)
|
|
{
|
|
onBuildingStateChanged(bs, DataModification::eAdded);
|
|
};
|
|
if (!dtcBld->buildingStates(cb))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
} // end of init()
|
|
//-----------------------------------------------------------------------------
|
|
int HandlerParticipantBuilding::getDamagePercentFromBuilding(const int buildingId) const
|
|
{
|
|
DEBUG_LOG(m_logger) << "getDamagePercentFromBuilding buildingId=" << buildingId;
|
|
auto it = m_buildingStates.find(buildingId);
|
|
return it != m_buildingStates.end() ? it.value().damagePercent() : 0;
|
|
}
|
|
|
|
int HandlerParticipantBuilding::getDamagePercentFromRoom(const int roomId) const
|
|
{
|
|
//int buildingId = m_handlerBuildingData->getBuildingIdFromRoomId(roomId);
|
|
int buildingId;
|
|
m_ddsHandler->dtcIsm()->getBuildingId(roomId, buildingId);
|
|
|
|
auto it = m_roomIdDamageState.find(roomId);
|
|
|
|
// Exception:
|
|
// if a building has failed completely, not all individual rooms are set as failed
|
|
DEBUG_LOG(m_logger) << "getDamagePercentFromBuilding=" << getDamagePercentFromBuilding(buildingId)
|
|
<< " buildingId=" << buildingId
|
|
<< " roomId=" << roomId;
|
|
if (buildingId < 0)
|
|
return -1;
|
|
if (getDamagePercentFromBuilding(buildingId) == PERCENT_100)
|
|
{
|
|
DEBUG_LOG(m_logger) << "return PERCENT_100:" << PERCENT_100;
|
|
return PERCENT_100;
|
|
}
|
|
return it != m_roomIdDamageState.end() ? it.value().damagePercent : 0;
|
|
}
|
|
|
|
void HandlerParticipantBuilding::onSendCesHitReply(const Core::FunctionReplyObject &replyObject)
|
|
{
|
|
//if (replyObject.error())
|
|
// WARNING_LOG(m_logger) << "Can not send hit on participant to training area: " << replyObject();
|
|
//else
|
|
m_requestMap.remove(replyObject.id());
|
|
DEBUG_LOG(m_logger) << "onSendCesHitReply for id " << replyObject.id() << " success"
|
|
<< " m_requestMap.remove(" << replyObject.id() << ")"
|
|
<< " m_requestMap.size=" << m_requestMap.size();
|
|
|
|
}
|
|
|
|
// ///////////////////////////////////
|
|
// B L D (Buildings)
|
|
// ///////////////////////////////////
|
|
void HandlerParticipantBuilding::onBuildingStateChanged(const Buildings::BuildingState &data, DataModification modType)
|
|
{
|
|
if (modType == DataModification::eRemoved)
|
|
{
|
|
m_buildingStates.remove(data.id());
|
|
return;
|
|
}
|
|
|
|
DEBUG_LOG(m_logger) << "Got BuildingState originatorParticipantId=" << data.originatorParticipantId()
|
|
<< ", aesId = " << data.aesId()
|
|
<< ", chargeTypeId = " << data.chargeTypeId()
|
|
<< ", sampleTime = " << data.sampleTime()
|
|
<< ", CountRooms =" << data.roomStates().size()
|
|
<< ", structureElementId=" << data.structureElementId()
|
|
<< ", assetId=" << data.assetId()
|
|
<< ", roomStates.size=" << data.roomStates().size()
|
|
<< ", damagePercent" << data.damagePercent();
|
|
|
|
if ( (data.originatorParticipantId() == 0) && (data.aesId() == 0) && (data.chargeTypeId()==0))
|
|
{
|
|
DEBUG_LOG(m_logger) << "Not valid return ";
|
|
return;
|
|
}
|
|
|
|
// fill m_roomIdDamageState
|
|
RoomState rs;
|
|
rs.buildingId = data.id();
|
|
m_buildingStates.insert(data.id(), data);
|
|
DEBUG_LOG(m_logger) << "m_buildingStates.insert id=" << data.id()
|
|
<< " aesId=" << data.aesId()
|
|
<< " name=" << data.name();
|
|
|
|
for (const Buildings::RoomState &roomState : data.roomStates())
|
|
{
|
|
rs.damagePercent = roomState.damagePercent();
|
|
m_roomIdDamageState.insert(roomState.id(), rs);
|
|
DEBUG_LOG(m_logger) << "m_roomIdDamageState.insert"
|
|
<< " RoomId = " << roomState.id()
|
|
<< ", BuildingId = " << data.id()
|
|
<< ", destruction = " << roomState.damagePercent();
|
|
}
|
|
// init: remove all rooms from Map
|
|
if (data.damagePercent() == 0)
|
|
{
|
|
auto it = m_roomIdDamageState.begin();
|
|
while (it != m_roomIdDamageState.end())
|
|
{
|
|
if (it.value().buildingId == data.id())
|
|
it = m_roomIdDamageState.erase(it);
|
|
else
|
|
++it;
|
|
}
|
|
return;
|
|
}
|
|
|
|
const auto participantsMap = m_handlerParticipant->positions();
|
|
for (const Buildings::RoomState &roomState : data.roomStates())
|
|
{
|
|
if (roomState.damagePercent() <= 0)
|
|
continue;
|
|
// no effect should not burden the radio
|
|
if (roomState.remainingEffectPercent() == 0)
|
|
continue;
|
|
|
|
DEBUG_LOG(m_logger) << " RoomId[" << roomState.id() << "]:"
|
|
<< " remainingEffectPercent = " << roomState.remainingEffectPercent()
|
|
<< " roomState.damagePercent()=" << roomState.damagePercent()
|
|
<< " roomState.remainingEffectPercent()=" << roomState.remainingEffectPercent();
|
|
// search for participants in each room:
|
|
// if participant in room sendCESHit to TAB
|
|
|
|
for (const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos : participantsMap)
|
|
{
|
|
const int participantId = participantPos.participantId();
|
|
if (participantPos.roomId() != roomState.id())
|
|
continue;
|
|
if (participantPos.vulnerabilityState == ProjectDataManagement::VulnerabilityState_def::CatastrophicKill)
|
|
continue;
|
|
const int equipNo = m_ddsHandler->participantId2EquipNo(participantId);
|
|
if (equipNo <= 0)
|
|
continue;
|
|
if (m_handlerParticipant->isOutdated(participantPos))
|
|
continue;
|
|
|
|
DEBUG_LOG(m_logger) << " participantId = " << participantId
|
|
<< " roomId = " << participantPos.roomId()
|
|
<< " roomState.id=" << roomState.id()
|
|
<< " participantPos.vulnerabilityState=" << participantPos.vulnerabilityState
|
|
<< " equipNo=" << m_ddsHandler->participantId2EquipNo(participantId)
|
|
<< " isOutdated=" << m_handlerParticipant->isOutdated(participantPos);
|
|
|
|
DEBUG_LOG(m_logger) << "sendCesHitToParticipant";
|
|
sendCesHitToParticipant(data, participantId, roomState.remainingEffectPercent());
|
|
}
|
|
}
|
|
|
|
m_buildingStates.insert(data.id(), data);
|
|
if (!m_timer->isActive() && !m_requestMap.isEmpty())
|
|
m_timer->start(1000);
|
|
|
|
emit newBuildingState(data.id());
|
|
}
|
|
|
|
void HandlerParticipantBuilding::sendCesHitToParticipant(const Buildings::BuildingState &data,
|
|
const int32_t participantId,
|
|
const int32_t remainingEffectPercent)
|
|
{
|
|
const int equipNo = m_ddsHandler->participantId2EquipNo(participantId);
|
|
const QHash<int, CentralEffectSimulation::HandlerParticipant::CesParticipantData> participantsMap = m_handlerParticipant->positions();
|
|
const int originatorEquipNo = m_ddsHandler->participantId2EquipNo(data.originatorParticipantId());
|
|
|
|
|
|
|
|
CentralEffectSimulation::HandlerParticipant::CesParticipantData participantPos = participantsMap.value(participantId);
|
|
const ProjectDataManagement::EventType eventType = ProjectDataManagement::EventType_def::HitBuilding;
|
|
|
|
AreaEffectSimulation::AesItem aesItem;
|
|
|
|
|
|
|
|
bool itemAvailable = m_ddsHandler->dtcAes()->aesItemFromId(data.aesId(), aesItem);
|
|
if (itemAvailable)
|
|
DEBUG_LOG(m_logger) << "partyId=" << aesItem.partyId()
|
|
<< " chargeTypeId=" << aesItem.chargeStruct().chargeTypeId()
|
|
<< " duration=" << aesItem.effectDuration();
|
|
|
|
// mineFieldBitIndex wird als reserve1 uegertragen und hier wird die Wirkdauer uebertragen.
|
|
const int duration = aesItem.effectDuration() / 1000;
|
|
|
|
//int32_t legacyChargeTypeId = 0;
|
|
//const ProjectDataManagement::FuseType fuseType = m_ddsHandler->dtcAes()->explosionCluster(aesItem.id()).fuseType();
|
|
const int chargeTypeId = itemAvailable ? aesItem.chargeStruct().chargeTypeId() : data.chargeTypeId();
|
|
|
|
// legacyChargeTypeId = m_ddsHandler->getLegacyIdFromChargeTypeId(chargeTypeId, fuseType);
|
|
// NOTE: igniterTypeId/IgniterFunction = 0 as long as BuildingState does not contain values
|
|
AreaEffectSimulation::ChargeStruct chargeStruct = { data.chargeTypeId(),0,0};
|
|
if (itemAvailable) chargeStruct = aesItem.chargeStruct();
|
|
int remainTasCodeIndirect = m_ddsHandler->remainingTasCode(chargeStruct);
|
|
|
|
DEBUG_LOG(m_logger) << " ftc sendCESHit to Participant equipNo = " << equipNo
|
|
<< " participantId=" << participantId
|
|
<< " chargeTypeId=" << data.chargeTypeId()
|
|
<< " originatorEquipNo=" << originatorEquipNo
|
|
<< " remainingEffectPercent=" << remainingEffectPercent
|
|
<< " remainTasCodeIndirect=" << remainTasCodeIndirect
|
|
<< " eventType=" << eventType;
|
|
const TrainingAreaBase::TabPosition pos(participantPos.pos(),
|
|
participantPos.reportingSource(),
|
|
participantPos.buildingId(),
|
|
participantPos.roomId());
|
|
|
|
|
|
// Bei Nebel soll die Weste nur einmal piepen und nicht regelmaessig. Das wird mit Wirkung = 3 uebertragen
|
|
// In fog, the waistcoat should only beep once and not regularly. This is transmitted with effect = 3
|
|
// int effect;
|
|
// if (m_ddsHandler->isSmoke(chargeTypeId))
|
|
// effect = 3;
|
|
// else
|
|
// effect = 2;
|
|
|
|
|
|
|
|
TrainingAreaBase::SendCesHitRequest requestTab;
|
|
|
|
requestTab.aesId(data.aesId());
|
|
//requestTab.chargeTypeId(legacyChargeTypeId > 0 ? legacyChargeTypeId : chargeTypeId);
|
|
requestTab.chargeTypeId(chargeTypeId);
|
|
requestTab.effectTime(data.sampleTime());
|
|
requestTab.equipmentNumber(equipNo);
|
|
requestTab.eventType(eventType);
|
|
requestTab.mineId(duration);
|
|
requestTab.originatorEquipmentNumber(originatorEquipNo);
|
|
requestTab.participantId(participantId);
|
|
int32_t partyId = 0;
|
|
if ( aesItem.partyId().is_set())
|
|
partyId = aesItem.partyId().get();
|
|
requestTab.partyId(partyId);
|
|
requestTab.position(pos);
|
|
|
|
// Same like direct Hit
|
|
// if (aesItem.id() > 0)
|
|
// {
|
|
// NOTICE_LOG(m_logger) << "remainEffectPercent Wirksimulation remainEffectPercent=" << remainTasCodeIndirect;
|
|
// requestTab.remainEffectPercent(remainTasCodeIndirect);
|
|
// }
|
|
// else
|
|
{
|
|
DEBUG_LOG(m_logger) << "direkter Beschuss remainEffectPercent=" << remainingEffectPercent;
|
|
requestTab.remainEffectPercent(remainingEffectPercent);
|
|
}
|
|
|
|
m_requestMap.insert(participantId, requestTab);
|
|
}
|
|
|
|
void HandlerParticipantBuilding::sendFtcCesHitRequestTimeout()
|
|
{
|
|
auto ftcTab = m_ddsHandler->ftcTab();
|
|
for (const TrainingAreaBase::SendCesHitRequest &hr : qAsConst(m_requestMap))
|
|
{
|
|
DEBUG_LOG(m_logger) << "sendFtcCesHitRequest: " << hr;
|
|
ftcTab->sendCesHitRequest(hr, this);
|
|
}
|
|
m_requestMap.clear();
|
|
}
|
|
|
|
} // namespace CesParticipantBuildings
|