From 4f333d44a0c72cd3b8e34b76c8774717ee2a8994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Wed, 10 Jul 2019 23:07:41 +0300 Subject: Fix CPhone crash, more functions --- src/control/Phones.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/control/Phones.h | 25 ++++++++++++-- 2 files changed, 112 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index 1d3a9777..028d80a9 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -1,8 +1,13 @@ #include "common.h" #include "patcher.h" #include "Phones.h" +#include "Pools.h" -CPhoneInfo &gPhoneInfo = * (CPhoneInfo*) * (uintptr*)0x732A20; +CPhoneInfo &gPhoneInfo = *(CPhoneInfo*)0x732A20; + +bool &CPhoneInfo::isPhonePickedUp = *(bool*)0x6283AC; +bool &CPhoneInfo::isPhoneBeingPickedUp = *(bool*)0x6283B4; +CPhone *&CPhoneInfo::pickedUpPhone = *(CPhone**)0x6283B0; int CPhoneInfo::FindNearestFreePhone(CVector *pos) @@ -12,7 +17,7 @@ CPhoneInfo::FindNearestFreePhone(CVector *pos) for (int phoneId = 0; phoneId < m_nMax; phoneId++) { - if (gPhoneInfo.m_aPhones[phoneId].m_nState == 0) { + if (gPhoneInfo.m_aPhones[phoneId].m_nState == PHONE_STATE_FREE) { float phoneDist = (m_aPhones[phoneId].m_vecPos - *pos).Magnitude2D(); if (phoneDist < nearestPhoneDist) { @@ -34,9 +39,91 @@ CPhoneInfo::PhoneAtThisPosition(CVector pos) return false; } +bool +CPhoneInfo::HasMessageBeenDisplayed(int phoneId) +{ + if (isPhonePickedUp) + return false; + + int state = m_aPhones[phoneId].m_nState; + + return state == PHONE_STATE_REPEATED_MESSAGE_SHOWN_ONCE || + state == PHONE_STATE_ONETIME_MESSAGE_SHOWN || + state == PHONE_STATE_REPEATED_MESSAGE_SHOWN; +} + +bool +CPhoneInfo::IsMessageBeingDisplayed(int phoneId) +{ + return pickedUpPhone == &m_aPhones[phoneId]; +} + +void +CPhoneInfo::Load(CPhoneInfo *source, uint8 buffer) +{ + // Buffer isn't used. + + m_nMax = source->m_nMax; + m_nNum = source->m_nNum; + for (int phoneId = 0; phoneId < 50; phoneId++) { + CPhone *phone = &source->m_aPhones[phoneId]; + + m_aPhones[phoneId].m_vecPos = phone->m_vecPos; + memcpy(m_aPhones[phoneId].m_apMessages, phone->m_apMessages, sizeof(uint16*) * 6); + m_aPhones[phoneId].m_pEntity = phone->m_pEntity; + m_aPhones[phoneId].m_nState = phone->m_nState; + m_aPhones[phoneId].field_30 = phone->field_30; + + if (phone->m_pEntity) { + // It's saved as building pool index in save file, convert it to true entity + CBuilding *actualEntity = CPools::GetBuildingPool()->GetSlot((int)phone->m_pEntity - 1); + m_aPhones[phoneId].m_pEntity = actualEntity; + } + } +} + +void +CPhoneInfo::SetPhoneMessage_JustOnce(int phoneId, uint16 *msg1, uint16 *msg2, uint16 *msg3, uint16 *msg4, uint16 *msg5, uint16 *msg6) +{ + // If there is at least one message, it should be msg1. + if (msg1) { + m_aPhones[phoneId].m_apMessages[0] = msg1; + m_aPhones[phoneId].m_apMessages[1] = msg2; + m_aPhones[phoneId].m_apMessages[2] = msg3; + m_aPhones[phoneId].m_apMessages[3] = msg4; + m_aPhones[phoneId].m_apMessages[4] = msg5; + m_aPhones[phoneId].m_apMessages[5] = msg6; + m_aPhones[phoneId].m_nState = PHONE_STATE_ONETIME_MESSAGE_SET; + } else { + m_aPhones[phoneId].m_nState = PHONE_STATE_MESSAGE_REMOVED; + } +} + +void +CPhoneInfo::SetPhoneMessage_Repeatedly(int phoneId, uint16 *msg1, uint16 *msg2, uint16 *msg3, uint16 *msg4, uint16 *msg5, uint16 *msg6) +{ + // If there is at least one message, it should be msg1. + if (msg1) { + m_aPhones[phoneId].m_apMessages[0] = msg1; + m_aPhones[phoneId].m_apMessages[1] = msg2; + m_aPhones[phoneId].m_apMessages[2] = msg3; + m_aPhones[phoneId].m_apMessages[3] = msg4; + m_aPhones[phoneId].m_apMessages[4] = msg5; + m_aPhones[phoneId].m_apMessages[5] = msg6; + m_aPhones[phoneId].m_nState = PHONE_STATE_REPEATED_MESSAGE_SET; + } else { + m_aPhones[phoneId].m_nState = PHONE_STATE_MESSAGE_REMOVED; + } +} + STARTPATCHES InjectHook(0x42F720, &CPhoneInfo::FindNearestFreePhone, PATCH_JUMP); InjectHook(0x42FD50, &CPhoneInfo::PhoneAtThisPosition, PATCH_JUMP); + InjectHook(0x42FFF0, &CPhoneInfo::HasMessageBeenDisplayed, PATCH_JUMP); + InjectHook(0x430030, &CPhoneInfo::IsMessageBeingDisplayed, PATCH_JUMP); + InjectHook(0x430120, &CPhoneInfo::Load, PATCH_JUMP); + InjectHook(0x42FF90, &CPhoneInfo::SetPhoneMessage_JustOnce, PATCH_JUMP); + InjectHook(0x42FF30, &CPhoneInfo::SetPhoneMessage_Repeatedly, PATCH_JUMP); ENDPATCHES WRAPPER void PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x42F570); } diff --git a/src/control/Phones.h b/src/control/Phones.h index 7ac34c3a..74f24d25 100644 --- a/src/control/Phones.h +++ b/src/control/Phones.h @@ -3,12 +3,25 @@ #include "Physical.h" #include "AnimBlendAssociation.h" +enum { + PHONE_STATE_FREE, + PHONE_STATE_1, + PHONE_STATE_2, + PHONE_STATE_MESSAGE_REMOVED, + PHONE_STATE_ONETIME_MESSAGE_SET, + PHONE_STATE_REPEATED_MESSAGE_SET, + PHONE_STATE_REPEATED_MESSAGE_SHOWN_ONCE, + PHONE_STATE_ONETIME_MESSAGE_SHOWN, + PHONE_STATE_REPEATED_MESSAGE_SHOWN, + PHONE_STATE_9 +}; + struct CPhone { CVector m_vecPos; uint16 *m_apMessages[6]; - int32 field_24; - CEntity *m_pEntity; + uint32 m_lastTimeRepeatedMsgShown; + CEntity *m_pEntity; // it's building pool index in save files int32 m_nState; uint8 field_30; }; @@ -16,6 +29,9 @@ struct CPhone static_assert(sizeof(CPhone) == 0x34, "CPhone: error"); class CPhoneInfo { + static bool &isPhonePickedUp; + static bool &isPhoneBeingPickedUp; + static CPhone *&pickedUpPhone; public: int32 m_nMax; int32 m_nNum; @@ -26,6 +42,11 @@ public: int FindNearestFreePhone(CVector*); bool PhoneAtThisPosition(CVector); + bool HasMessageBeenDisplayed(int); + bool IsMessageBeingDisplayed(int); + void Load(CPhoneInfo *source, uint8 buffer); + void SetPhoneMessage_JustOnce(int phoneId, uint16 *msg1, uint16 *msg2, uint16 *msg3, uint16 *msg4, uint16 *msg5, uint16 *msg6); + void SetPhoneMessage_Repeatedly(int phoneId, uint16 *msg1, uint16 *msg2, uint16 *msg3, uint16 *msg4, uint16 *msg5, uint16 *msg6); }; extern CPhoneInfo &gPhoneInfo; -- cgit v1.2.3