Fix racing imagination loss on death (#1006)

* Fix imagination on death

* Fix defaults

* Fix visuals
This commit is contained in:
David Markowitz 2023-03-05 12:34:59 -08:00 committed by GitHub
parent 9d65d871d0
commit 49047a267b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 85 additions and 34 deletions

View File

@ -546,6 +546,8 @@ enum GAME_MSG : unsigned short {
GAME_MSG_REMOVE_RUN_SPEED_MODIFIER = 1506, GAME_MSG_REMOVE_RUN_SPEED_MODIFIER = 1506,
GAME_MSG_UPDATE_PROPERTY_PERFORMANCE_COST = 1547, GAME_MSG_UPDATE_PROPERTY_PERFORMANCE_COST = 1547,
GAME_MSG_PROPERTY_ENTRANCE_BEGIN = 1553, GAME_MSG_PROPERTY_ENTRANCE_BEGIN = 1553,
GAME_MSG_SET_RESURRECT_RESTORE_VALUES = 1591,
GAME_MSG_VEHICLE_STOP_BOOST = 1617,
GAME_MSG_REMOVE_BUFF = 1648, GAME_MSG_REMOVE_BUFF = 1648,
GAME_MSG_REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1666, GAME_MSG_REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1666,
GAME_MSG_RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1667, GAME_MSG_RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1667,

View File

@ -306,30 +306,58 @@ void RacingControlComponent::OnRequestDie(Entity* player) {
auto* vehicle = auto* vehicle =
EntityManager::Instance()->GetEntity(racingPlayer.vehicleID); EntityManager::Instance()->GetEntity(racingPlayer.vehicleID);
if (vehicle == nullptr) { if (!vehicle) return;
return;
}
if (!racingPlayer.noSmashOnReload) { if (!racingPlayer.noSmashOnReload) {
racingPlayer.smashedTimes++; racingPlayer.smashedTimes++;
GameMessages::SendDie(vehicle, vehicle->GetObjectID(), LWOOBJID_EMPTY, true,
VIOLENT, u"", 0, 0, 90.0f, false, true, 0);
auto* destroyableComponent = vehicle->GetComponent<DestroyableComponent>();
uint32_t respawnImagination = 0;
// Reset imagination to half its current value, rounded up to the nearest value divisible by 10, as it was done in live.
// Do not actually change the value yet. Do that on respawn.
if (destroyableComponent) {
respawnImagination = static_cast<int32_t>(ceil(destroyableComponent->GetImagination() / 2.0f / 10.0f)) * 10.0f;
GameMessages::SendSetResurrectRestoreValues(vehicle, -1, -1, respawnImagination);
}
// Respawn the player in 2 seconds, as was done in live. Not sure if this value is in a setting somewhere else...
vehicle->AddCallbackTimer(2.0f, [=]() {
if (!vehicle || !this->m_Parent) return;
GameMessages::SendRacingResetPlayerToLastReset(
m_Parent->GetObjectID(), racingPlayer.playerID,
UNASSIGNED_SYSTEM_ADDRESS);
GameMessages::SendVehicleStopBoost(vehicle, player->GetSystemAddress(), true);
GameMessages::SendRacingSetPlayerResetInfo(
m_Parent->GetObjectID(), racingPlayer.lap,
racingPlayer.respawnIndex, player->GetObjectID(),
racingPlayer.respawnPosition, racingPlayer.respawnIndex + 1,
UNASSIGNED_SYSTEM_ADDRESS);
GameMessages::SendResurrect(vehicle);
auto* destroyableComponent = vehicle->GetComponent<DestroyableComponent>();
// Reset imagination to half its current value, rounded up to the nearest value divisible by 10, as it was done in live.
if (destroyableComponent) destroyableComponent->SetImagination(respawnImagination);
EntityManager::Instance()->SerializeEntity(vehicle);
});
auto* characterComponent = player->GetComponent<CharacterComponent>();
if (characterComponent != nullptr) {
characterComponent->UpdatePlayerStatistic(RacingTimesWrecked);
}
} else {
GameMessages::SendRacingSetPlayerResetInfo(
m_Parent->GetObjectID(), racingPlayer.lap,
racingPlayer.respawnIndex, player->GetObjectID(),
racingPlayer.respawnPosition, racingPlayer.respawnIndex + 1,
UNASSIGNED_SYSTEM_ADDRESS);
GameMessages::SendRacingResetPlayerToLastReset(
m_Parent->GetObjectID(), racingPlayer.playerID,
UNASSIGNED_SYSTEM_ADDRESS);
} }
// Reset player to last checkpoint
GameMessages::SendRacingSetPlayerResetInfo(
m_Parent->GetObjectID(), racingPlayer.lap,
racingPlayer.respawnIndex, player->GetObjectID(),
racingPlayer.respawnPosition, racingPlayer.respawnIndex + 1,
UNASSIGNED_SYSTEM_ADDRESS);
GameMessages::SendRacingResetPlayerToLastReset(
m_Parent->GetObjectID(), racingPlayer.playerID,
UNASSIGNED_SYSTEM_ADDRESS);
auto* characterComponent = player->GetComponent<CharacterComponent>();
if (characterComponent != nullptr) {
characterComponent->UpdatePlayerStatistic(RacingTimesWrecked);
}
return;
} }
} }
@ -348,19 +376,6 @@ void RacingControlComponent::OnRacingPlayerInfoResetFinished(Entity* player) {
return; return;
} }
if (!racingPlayer.noSmashOnReload) {
GameMessages::SendDie(vehicle, LWOOBJID_EMPTY, LWOOBJID_EMPTY, true,
VIOLENT, u"", 0, 0, 0, true, false, 0);
GameMessages::SendVehicleUnlockInput(racingPlayer.vehicleID, false,
UNASSIGNED_SYSTEM_ADDRESS);
GameMessages::SendVehicleSetWheelLockState(
racingPlayer.vehicleID, false, false,
UNASSIGNED_SYSTEM_ADDRESS);
GameMessages::SendResurrect(vehicle);
}
racingPlayer.noSmashOnReload = false; racingPlayer.noSmashOnReload = false;
return; return;

View File

@ -4396,6 +4396,36 @@ void GameMessages::SendRacingResetPlayerToLastReset(LWOOBJID objectId, LWOOBJID
SEND_PACKET; SEND_PACKET;
} }
void GameMessages::SendVehicleStopBoost(Entity* targetEntity, const SystemAddress& playerSysAddr, bool affectPassive) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(targetEntity->GetObjectID());
bitStream.Write(GAME_MSG::GAME_MSG_VEHICLE_STOP_BOOST);
bitStream.Write(affectPassive);
SEND_PACKET_BROADCAST;
}
void GameMessages::SendSetResurrectRestoreValues(Entity* targetEntity, int32_t armorRestore, int32_t healthRestore, int32_t imaginationRestore) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(targetEntity->GetObjectID());
bitStream.Write(GAME_MSG::GAME_MSG_SET_RESURRECT_RESTORE_VALUES);
bitStream.Write(armorRestore != -1);
if (armorRestore != -1) bitStream.Write(armorRestore);
bitStream.Write(healthRestore != -1);
if (healthRestore != -1) bitStream.Write(healthRestore);
bitStream.Write(imaginationRestore != -1);
if (imaginationRestore != -1) bitStream.Write(imaginationRestore);
SEND_PACKET_BROADCAST;
}
void GameMessages::SendNotifyRacingClient(LWOOBJID objectId, int32_t eventType, int32_t param1, LWOOBJID paramObj, std::u16string paramStr, LWOOBJID singleClient, const SystemAddress& sysAddr) { void GameMessages::SendNotifyRacingClient(LWOOBJID objectId, int32_t eventType, int32_t param1, LWOOBJID paramObj, std::u16string paramStr, LWOOBJID singleClient, const SystemAddress& sysAddr) {
CBITSTREAM; CBITSTREAM;

View File

@ -31,7 +31,8 @@ namespace GameMessages {
void SendPlayerAllowedRespawn(LWOOBJID entityID, bool doNotPromptRespawn, const SystemAddress& systemAddress); void SendPlayerAllowedRespawn(LWOOBJID entityID, bool doNotPromptRespawn, const SystemAddress& systemAddress);
void SendInvalidZoneTransferList(Entity* entity, const SystemAddress& sysAddr, const std::u16string& feedbackURL, const std::u16string& invalidMapTransferList, bool feedbackOnExit, bool feedbackOnInvalidTransfer); void SendInvalidZoneTransferList(Entity* entity, const SystemAddress& sysAddr, const std::u16string& feedbackURL, const std::u16string& invalidMapTransferList, bool feedbackOnExit, bool feedbackOnInvalidTransfer);
void SendKnockback(const LWOOBJID& objectID, const LWOOBJID& caster, const LWOOBJID& originator, int knockBackTimeMS, const NiPoint3& vector); void SendKnockback(const LWOOBJID& objectID, const LWOOBJID& caster, const LWOOBJID& originator, int knockBackTimeMS, const NiPoint3& vector);
// https://lcdruniverse.org/lu_packets/lu_packets/world/gm/client/struct.VehicleStopBoost.html
void SendVehicleStopBoost(Entity* targetEntity, const SystemAddress& playerSysAddr, bool affectPassive);
void SendStartArrangingWithItem( void SendStartArrangingWithItem(
Entity* entity, Entity* entity,
const SystemAddress& sysAddr, const SystemAddress& sysAddr,
@ -125,6 +126,9 @@ namespace GameMessages {
void HandleUnUseModel(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); void HandleUnUseModel(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
void SendStartCelebrationEffect(Entity* entity, const SystemAddress& sysAddr, int celebrationID); void SendStartCelebrationEffect(Entity* entity, const SystemAddress& sysAddr, int celebrationID);
// https://lcdruniverse.org/lu_packets/lu_packets/world/gm/client/struct.SetResurrectRestoreValues.html
void SendSetResurrectRestoreValues(Entity* targetEntity, int32_t armorRestore, int32_t healthRestore, int32_t imaginationRestore);
/** /**
* Sends a message to an Entity to smash itself, but not delete or destroy itself from the world * Sends a message to an Entity to smash itself, but not delete or destroy itself from the world
* *