#include "common.h" #include "main.h" #include "Camera.h" #include "Coronas.h" #include "Darkel.h" #include "Entity.h" #include "Explosion.h" #include "Font.h" #include "Garages.h" #include "General.h" #include "ModelIndices.h" #include "Object.h" #include "Pad.h" #include "Pickups.h" #include "PlayerPed.h" #include "Wanted.h" #include "DMAudio.h" #include "Fire.h" #include "PointLights.h" #include "Pools.h" #ifdef FIX_BUGS #include "Replay.h" #endif #include "Script.h" #include "Shadows.h" #include "SpecialFX.h" #include "Sprite.h" #include "Timer.h" #include "WaterLevel.h" #include "World.h" #include "Hud.h" #include "Messages.h" #include "Streaming.h" // --MIAMI: file done CPickup CPickups::aPickUps[NUMPICKUPS]; int16 CPickups::NumMessages; int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS]; int16 CPickups::CollectedPickUpIndex; int32 CPickups::PlayerOnWeaponPickup; int32 CollectPickupBuffer; // unused bool CPickups::bPickUpcamActivated; CVehicle *CPickups::pPlayerVehicle; CVector CPickups::StaticCamCoors; uint32 CPickups::StaticCamStartTime; tPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES]; uint16 AmmoForWeapon[WEAPONTYPE_TOTALWEAPONS + 1] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 8, 8, 8, 68, 24, 32, 28, 20, 200, 120, 120, 120, 120, 120, 40, 28, 8, 300, 200, 1000, 1, 400, 36, 0 }; uint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS + 1] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 34, 12, 16, 14, 10, 100, 60, 60, 60, 60, 60, 20, 14, 4, 150, 100, 500, 1, 400, 36, 0 }; uint16 CostOfWeapon[WEAPONTYPE_TOTALWEAPONS + 3] = { 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1000, 1000, 1000, 500, 8000, 250, 400, 1200, 1250, 1250, 800, 800, 650, 1200, 5000, 400, 10000, 10000, 8000, 8000, 8000, 10000, 1000, 11000, 500, 20, 10, 0 }; struct { uint8 r,g,b; float unk; } aPickupColors[] = { { 128, 128, 128, 1.0f }, { 128, 128, 128, 1.0f }, { 97, 194, 247, 1.0f }, { 97, 194, 247, 1.0f }, { 97, 194, 247, 1.0f }, { 97, 194, 247, 1.0f }, { 97, 194, 247, 1.0f }, { 97, 194, 247, 1.0f }, { 97, 194, 247, 1.0f }, { 97, 194, 247, 1.0f }, { 97, 194, 247, 1.0f }, { 97, 194, 247, 1.0f }, { 27, 89, 130, 1.0f }, { 27, 89, 130, 1.0f }, { 27, 89, 130, 1.0f }, { 27, 89, 130, 1.0f }, { 27, 89, 130, 1.0f }, { 149, 194, 24, 1.0f }, { 149, 194, 24, 1.0f }, { 45, 155, 90, 1.0f }, { 45, 155, 90, 1.0f }, { 45, 155, 90, 1.0f }, { 255, 227, 79, 1.0f }, { 255, 227, 79, 1.0f }, { 255, 227, 79, 1.0f }, { 255, 227, 79, 1.0f }, { 254, 137, 0, 1.0f }, { 254, 137, 0, 1.0f }, { 249, 131, 215, 1.0f }, { 249, 131, 215, 1.0f }, { 164, 40, 178, 1.0f }, { 164, 40, 178, 1.0f }, { 164, 40, 178, 1.0f }, { 164, 40, 178, 1.0f }, { 69, 69, 69, 1.0f }, { 69, 69, 69, 1.0f }, { 69, 69, 69, 1.0f }, { 255, 100, 100, 1.0f }, { 128, 255, 128, 1.0f }, { 100, 100, 255, 1.0f }, { 255, 255, 100, 1.0f }, { 255, 100, 100, 1.0f }, { 100, 255, 100, 1.0f }, { 255, 255, 255, 1.0f } }; void ModifyStringLabelForControlSetting(char *str) { int len = (int)strlen(str); if (len <= 2) return; if (str[len - 2] != '_') return; switch (CPad::GetPad(0)->Mode) { case 0: case 1: str[len - 1] = 'L'; break; case 2: str[len - 1] = 'T'; break; case 3: str[len - 1] = 'C'; break; default: return; } } inline bool IsWeaponSlotAmmoMergeable(uint32 slot) { return slot == WEAPONSLOT_SHOTGUN || slot == WEAPONSLOT_SUBMACHINEGUN || slot == WEAPONSLOT_RIFLE; } void CPickup::ExtractAmmoFromPickup(CPlayerPed *player) { eWeaponType weaponType = CPickups::WeaponForModel(m_pObject->GetModelIndex()); if (m_eType == PICKUP_IN_SHOP || !IsWeaponSlotAmmoMergeable(CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot)) return; uint32 ammo = m_nQuantity; if (ammo == 0) { if (!m_bWasAmmoCollected) ammo = AmmoForWeapon_OnStreet[weaponType]; else goto removeAmmo; } player->GrantAmmo(weaponType, ammo); DMAudio.PlayOneShot(player->m_audioEntityId, SOUND_WEAPON_RELOAD, weaponType); // BUG? weapon type as volume, wtf? removeAmmo: m_nQuantity = 0; m_bWasAmmoCollected = true; } void CPickup::Remove() { GetRidOfObjects(); m_bRemoved = true; m_eType = PICKUP_NONE; } CObject * CPickup::GiveUsAPickUpObject(CObject **ppObject, CObject **ppExtraObject, int32 handle, int32 extraHandle) { CObject *&object = *ppObject; CObject *&extraObject = *ppExtraObject; object = extraObject = nil; int32 modelId = -1; if (CModelInfo::GetModelInfo(m_eModelIndex)->GetModelType() == MITYPE_WEAPON) { CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(((CWeaponModelInfo*)CModelInfo::GetModelInfo(m_eModelIndex))->GetWeaponInfo()); modelId = weaponInfo->m_nModelId; if (modelId == m_eModelIndex) modelId = weaponInfo->m_nModel2Id; } if (handle >= 0) { CPools::MakeSureSlotInObjectPoolIsEmpty(handle); if (extraHandle >= 0) CPools::MakeSureSlotInObjectPoolIsEmpty(extraHandle); if (object == nil) object = new(handle) CObject(m_eModelIndex, false); if (extraHandle >= 0 && modelId != -1 && extraObject == nil) extraObject = new(extraHandle) CObject(modelId, false); } else { object = new CObject(m_eModelIndex, false); if (modelId != -1) extraObject = new CObject(modelId, false); } if (object == nil) return nil; object->ObjectCreatedBy = MISSION_OBJECT; object->SetPosition(m_vecPos); object->SetOrientation(0.0f, 0.0f, -HALFPI); object->GetMatrix().UpdateRW(); object->UpdateRwFrame(); object->bAffectedByGravity = false; object->bExplosionProof = true; object->bUsesCollision = false; object->bIsPickup = true; object->bAmmoCollected = m_bWasAmmoCollected; object->bHasPreRenderEffects = true; if (extraObject) { extraObject->ObjectCreatedBy = MISSION_OBJECT; extraObject->SetPosition(m_vecPos); extraObject->SetOrientation(0.0f, 0.0f, -HALFPI); extraObject->GetMatrix().UpdateRW(); extraObject->UpdateRwFrame(); extraObject->bAffectedByGravity = false; extraObject->bExplosionProof = true; extraObject->bUsesCollision = false; extraObject->bIsPickup = true; extraObject->bAmmoCollected = true; extraObject->bHasPreRenderEffects = true; extraObject->m_nBonusValue = 0; extraObject->bPickupObjWithMessage = false; extraObject->bOutOfStock = false; } object->m_nBonusValue = (m_eModelIndex == MI_PICKUP_BONUS || m_eModelIndex == MI_PICKUP_CLOTHES) ? m_nQuantity : 0; switch (m_eType) { case PICKUP_IN_SHOP: object->bPickupObjWithMessage = true; object->bOutOfStock = false; if (m_eModelIndex == MI_PICKUP_HEALTH || m_eModelIndex == MI_PICKUP_ADRENALINE) object->m_nCostValue = 0; else object->m_nCostValue = CostOfWeapon[CPickups::WeaponForModel(m_eModelIndex)]; break; case PICKUP_ON_STREET: case PICKUP_ONCE: case PICKUP_ONCE_TIMEOUT: case PICKUP_COLLECTABLE1: case PICKUP_MONEY: case PICKUP_MINE_INACTIVE: case PICKUP_MINE_ARMED: case PICKUP_NAUTICAL_MINE_INACTIVE: case PICKUP_NAUTICAL_MINE_ARMED: case PICKUP_FLOATINGPACKAGE: case PICKUP_ON_STREET_SLOW: object->bPickupObjWithMessage = false; object->bOutOfStock = false; break; case PICKUP_IN_SHOP_OUT_OF_STOCK: object->bPickupObjWithMessage = false; object->bOutOfStock = true; object->bRenderScorched = true; break; case PICKUP_FLOATINGPACKAGE_FLOATING: default: break; } return object; } bool CPickup::CanBePickedUp(CPlayerPed *player, int playerId) { assert(m_pObject != nil); bool cannotBePickedUp = (m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > CWorld::Players[playerId].m_nMaxArmour - 0.5f) || (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > CWorld::Players[playerId].m_nMaxHealth - 0.5f) || (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE && player->m_pWanted->m_nWantedLevel == 0) || (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame)); return !cannotBePickedUp; } bool CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId) { bool result = false; float waterLevel; if (m_pObject) { m_pObject->GetMatrix().GetPosition() = m_vecPos; if (m_pExtraObject) m_pExtraObject->GetMatrix().GetPosition() = m_vecPos; } if (m_eType == PICKUP_ASSET_REVENUE) { uint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nTimer; m_nTimer = CTimer::GetTimeInMilliseconds(); if (Distance(FindPlayerCoors(), m_vecPos) > 10.0f) m_fRevenue += float(timePassed * m_nMoneySpeed) / SQR(1200.0f); m_fRevenue = Min(m_fRevenue, m_nQuantity); m_pObject->m_nCostValue = m_fRevenue < 10 ? 0 : m_fRevenue; } if (m_bRemoved) { if (CTimer::GetTimeInMilliseconds() > m_nTimer) { // respawn pickup if we're far enough float dist = (FindPlayerCoors().x - m_vecPos.x) * (FindPlayerCoors().x - m_vecPos.x) + (FindPlayerCoors().y - m_vecPos.y) * (FindPlayerCoors().y - m_vecPos.y); if (dist > 100.0f || m_eType == PICKUP_IN_SHOP && dist > 2.4f) { m_pObject = GiveUsAPickUpObject(&m_pObject, &m_pExtraObject, -1, -1); if (m_pObject) { CWorld::Add(m_pObject); m_bRemoved = false; } } } return false; } if (!m_pObject) { GiveUsAPickUpObject(&m_pObject, &m_pExtraObject, -1, -1); if (m_pObject) CWorld::Add(m_pObject); if (m_pExtraObject) CWorld::Add(m_pExtraObject); } if (!m_pObject) return false; if (!IsMine()) { // let's check if we touched the pickup bool isPickupTouched = false; if (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE) { if (vehicle != nil) { if (vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) isPickupTouched = true; } else { if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) { if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) + (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f) isPickupTouched = true; } } } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA) { if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) { isPickupTouched = true; } } else if (vehicle == nil) { if (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) { if ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) + (player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f) isPickupTouched = true; } } if (isPickupTouched) { eWeaponType weaponType = CPickups::WeaponForModel(m_pObject->GetModelIndex()); if (weaponType < WEAPONTYPE_TOTALWEAPONS && CDarkel::FrenzyOnGoing()) { isPickupTouched = false; m_bWasControlMessageShown = false; } else if (weaponType != WEAPONTYPE_UNARMED) { uint32 slot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot; eWeaponType plrWeaponSlot = FindPlayerPed()->GetWeapon(slot).m_eWeaponType; if (plrWeaponSlot != weaponType) { if (CStreaming::ms_aInfoForModel[m_pObject->GetModelIndex()].m_loadState == STREAMSTATE_LOADED) { if (plrWeaponSlot == WEAPONTYPE_UNARMED || (FindPlayerPed()->GetWeapon(slot).m_nAmmoTotal == 0 && !IsWeaponSlotAmmoMergeable(slot))) { if (CTimer::GetTimeInMilliseconds() - FindPlayerPed()->m_nPadDownPressedInMilliseconds < 1500) { CPickups::PlayerOnWeaponPickup = 6; isPickupTouched = false; } } else { CPickups::PlayerOnWeaponPickup = 6; if (IsWeaponSlotAmmoMergeable(slot)) { if (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_ONCE || m_eType == PICKUP_ON_STREET) { ExtractAmmoFromPickup(player); FindPlayerPed()->GetWeapon(slot).Reload(); } } if (!m_bWasControlMessageShown) { switch (CPad::GetPad(0)->Mode) { case 0: case 1: CHud::SetHelpMessage(TheText.Get("PU_CF1"), false); break; case 2: CHud::SetHelpMessage(TheText.Get("PU_CF3"), false); break; case 3: CHud::SetHelpMessage(TheText.Get("PU_CF4"), false); break; default: break; } m_bWasControlMessageShown = true; } if (CollectPickupBuffer == 0) isPickupTouched = false; if (CTimer::GetTimeInMilliseconds() - FindPlayerPed()->m_nPadDownPressedInMilliseconds < 1500) isPickupTouched = false; } } else isPickupTouched = false; } } } else m_bWasControlMessageShown = false; // if we didn't then we've got nothing to do if (isPickupTouched && CanBePickedUp(player, playerId)) { if (m_pObject->GetModelIndex() != MI_PICKUP_PROPERTY && m_pObject->GetModelIndex() != MI_PICKUP_PROPERTY_FORSALE) CPad::GetPad(0)->StartShake(120, 100); eWeaponType weaponType = CPickups::WeaponForModel(m_pObject->GetModelIndex()); switch (m_eType) { case PICKUP_IN_SHOP: if (CWorld::Players[playerId].m_nMoney < CostOfWeapon[weaponType]) CGarages::TriggerMessage("PU_MONY", -1, 6000, -1); else { CWorld::Players[playerId].m_nMoney -= CostOfWeapon[weaponType]; if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) { if (!player->DoesPlayerWantNewWeapon(weaponType, false)) break; player->GiveWeapon(weaponType, AmmoForWeapon[weaponType]); player->m_nSelectedWepSlot = player->GetWeaponSlot(weaponType); DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, m_pObject->GetModelIndex() - MI_GRENADE); } result = true; Remove(); } break; case PICKUP_ON_STREET: case PICKUP_ON_STREET_SLOW: if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) { if (!player->DoesPlayerWantNewWeapon(weaponType, false)) break; if (weaponType != WEAPONTYPE_UNARMED) { player->GiveWeapon(weaponType, m_nQuantity != 0 ? m_nQuantity : (m_bWasAmmoCollected ? 0 : AmmoForWeapon_OnStreet[weaponType]), true); if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED)) player->m_nSelectedWepSlot = player->GetWeaponSlot(weaponType); DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE); } else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA && vehicle != nil) { DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); CPickups::bPickUpcamActivated = true; CPickups::pPlayerVehicle = FindPlayerVehicle(); CPickups::StaticCamCoors = m_pObject->GetPosition(); CPickups::StaticCamStartTime = CTimer::GetTimeInMilliseconds(); } } if (m_eType == PICKUP_ON_STREET) m_nTimer = CTimer::GetTimeInMilliseconds() + 30000; else if (m_eType == PICKUP_ON_STREET_SLOW) { if (MI_PICKUP_BRIBE == m_pObject->GetModelIndex()) m_nTimer = CTimer::GetTimeInMilliseconds() + 300000; else m_nTimer = CTimer::GetTimeInMilliseconds() + 720000; } result = true; GetRidOfObjects(); m_bRemoved = true; break; case PICKUP_ONCE: case PICKUP_ONCE_TIMEOUT: case PICKUP_ONCE_TIMEOUT_SLOW: if (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) { if (!player->DoesPlayerWantNewWeapon(weaponType, false)) { ExtractAmmoFromPickup(player); break; } if (weaponType != WEAPONTYPE_UNARMED) { player->GiveWeapon(weaponType, m_nQuantity != 0 ? m_nQuantity : (m_bWasAmmoCollected ? 0 : AmmoForWeapon[weaponType]), true); if (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED)) player->m_nSelectedWepSlot = player->GetWeaponSlot(weaponType); } if (MI_PICKUP_SAVEGAME != m_pObject->GetModelIndex()) DMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE); } result = true; Remove(); break; case PICKUP_COLLECTABLE1: CWorld::Players[playerId].m_nCollectedPackages++; CWorld::Players[playerId].m_nMoney += 100; if (CWorld::Players[playerId].m_nCollectedPackages == CWorld::Players[playerId].m_nTotalPackages) { printf("All collectables have been picked up\n"); CGarages::TriggerMessage("CO_ALL", -1, 5000, -1); CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 100000; } else CGarages::TriggerMessage("CO_ONE", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages); result = true; Remove(); DMAudio.PlayFrontEndSound(SOUND_PICKUP_HIDDEN_PACKAGE, 0); return true; case PICKUP_MONEY: CWorld::Players[playerId].m_nMoney += m_nQuantity; sprintf(gString, "$%d", m_nQuantity); #ifdef MONEY_MESSAGES CMoneyMessages::RegisterOne(m_vecPos + CVector(0.0f, 0.0f, 1.0f), gString, 0, 255, 0, 0.5f, 0.5f); #endif result = true; Remove(); DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0); return true; case PICKUP_ASSET_REVENUE: CWorld::Players[CWorld::PlayerInFocus].m_nMoney += m_fRevenue; m_fRevenue = 0.0f; DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0); return false; case PICKUP_PROPERTY_LOCKED: if (!m_bWasControlMessageShown) { m_bWasControlMessageShown = true; CHud::SetHelpMessage(TheText.Get(m_sTextKey), false); } break; case PICKUP_PROPERTY_FORSALE: ModifyStringLabelForControlSetting(m_sTextKey); CMessages::InsertNumberInString(TheText.Get(m_sTextKey), m_nQuantity, 0, 0, 0, 0, 0, gUString); if (!CHud::IsHelpMessageBeingDisplayed()) CHud::SetHelpMessage(gUString, false); if (CollectPickupBuffer == 0) break; if (CTheScripts::IsPlayerOnAMission()) CHud::SetHelpMessage(TheText.Get("PROP_2"), true); else { if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney >= m_nQuantity) { CWorld::Players[CWorld::PlayerInFocus].m_nMoney -= m_nQuantity; CHud::SetHelpMessage(nil, true); result = true; Remove(); break; } CHud::SetHelpMessage(TheText.Get("PROP_1"), true); } break; default: break; } } } else { switch (m_eType) { case PICKUP_MINE_INACTIVE: if (vehicle != nil && !vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) { m_eType = PICKUP_MINE_ARMED; m_nTimer = CTimer::GetTimeInMilliseconds() + 10000; } break; case PICKUP_NAUTICAL_MINE_INACTIVE: { if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false)) m_pObject->GetMatrix().GetPosition().z = waterLevel + 0.6f; m_pObject->GetMatrix().UpdateRW(); m_pObject->UpdateRwFrame(); bool touched = false; for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) { CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i); if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) { touched = true; #ifdef FIX_BUGS break; // added break here #endif } } if (!touched) { m_eType = PICKUP_NAUTICAL_MINE_ARMED; m_nTimer = CTimer::GetTimeInMilliseconds() + 10000; } break; } case PICKUP_NAUTICAL_MINE_ARMED: if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false)) m_pObject->GetMatrix().GetPosition().z = waterLevel + 0.6f; m_pObject->GetMatrix().UpdateRW(); m_pObject->UpdateRwFrame(); // no break here case PICKUP_MINE_ARMED: { bool explode = false; if (CTimer::GetTimeInMilliseconds() > m_nTimer) explode = true; else {// added else here since vehicle lookup is useless for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) { CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i); if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) { explode = true; #ifdef FIX_BUGS break; // added break here #endif } } } if (explode) { CExplosion::AddExplosion(nil, nil, EXPLOSION_MINE, m_pObject->GetPosition(), 0); Remove(); } break; } case PICKUP_FLOATINGPACKAGE: m_pObject->m_vecMoveSpeed.z -= 0.01f * CTimer::GetTimeStep(); m_pObject->GetMatrix().GetPosition() += m_pObject->GetMoveSpeed() * CTimer::GetTimeStep(); m_pObject->GetMatrix().UpdateRW(); m_pObject->UpdateRwFrame(); if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0) && waterLevel >= m_pObject->GetPosition().z) m_eType = PICKUP_FLOATINGPACKAGE_FLOATING; break; case PICKUP_FLOATINGPACKAGE_FLOATING: if (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, 0)) m_pObject->GetMatrix().GetPosition().z = waterLevel; m_pObject->GetMatrix().UpdateRW(); m_pObject->UpdateRwFrame(); if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) { Remove(); result = true; DMAudio.PlayFrontEndSound(SOUND_PICKUP_FLOAT_PACKAGE, 0); } break; default: break; } } if (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_ONCE_TIMEOUT_SLOW || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer) Remove(); return result; } void CPickup::ProcessGunShot(CVector *vec1, CVector *vec2) { CColLine line(*vec1, *vec2); if (m_pObject) { CColSphere sphere; sphere.radius = 4.0f; sphere.center = m_pObject->GetPosition(); if (CCollision::TestLineSphere(line, sphere)) { CExplosion::AddExplosion(nil, nil, EXPLOSION_MINE, m_pObject->GetPosition(), 0); CWorld::Remove(m_pObject); delete m_pObject; m_pObject = nil; m_bRemoved = true; m_eType = PICKUP_NONE; } } } void CPickup::GetRidOfObjects() { if (m_pObject) { CWorld::Remove(m_pObject); delete m_pObject; m_pObject = nil; } if (m_pExtraObject) { CWorld::Remove(m_pExtraObject); delete m_pExtraObject; m_pExtraObject = nil; } } void CPickups::Init(void) { NumMessages = 0; for (int i = 0; i < NUMPICKUPS; i++) { aPickUps[i].m_eType = PICKUP_NONE; aPickUps[i].m_nIndex = 1; aPickUps[i].m_pObject = nil; aPickUps[i].m_pExtraObject = nil; } for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++) aPickUpsCollected[i] = 0; CollectedPickUpIndex = 0; } bool CPickups::TestForPickupsInBubble(CVector pos, float range) { for (int i = 0; i < NUMPICKUPS; i++) { if ((aPickUps[i].m_vecPos - pos).Magnitude() < range) return true; } return false; } bool CPickups::TryToMerge_WeaponType(CVector pos, eWeaponType weapon, uint8 type, uint32 quantity, bool unused) { for (int i = 0; i < NUMPICKUPS; i++) { if (aPickUps[i].m_eType == type && aPickUps[i].m_eModelIndex == ModelForWeapon(weapon)) if ((aPickUps[i].m_vecPos - pos).Magnitude() < 7.5f) { aPickUps[i].m_nQuantity += quantity; return true; } } return false; } bool CPickups::IsPickUpPickedUp(int32 pickupId) { for (int i = 0; i < NUMCOLLECTEDPICKUPS; i++) { if (pickupId == aPickUpsCollected[i]) { aPickUpsCollected[i] = 0; return true; } } return false; } void CPickups::PassTime(uint32 time) { for (int i = 0; i < NUMPICKUPS; i++) { if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_eType != PICKUP_ASSET_REVENUE) { if (aPickUps[i].m_nTimer <= time) aPickUps[i].m_nTimer = 0; else aPickUps[i].m_nTimer -= time; } } } int32 CPickups::GetActualPickupIndex(int32 index) { if (index == -1) return -1; // doesn't look nice if ((uint16)((index & 0xFFFF0000) >> 16) != aPickUps[(uint16)index].m_nIndex) return -1; return (uint16)index; } bool CPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex) { CPlayerPed *player; if (playerIndex <= 0) player = CWorld::Players[CWorld::PlayerInFocus].m_pPed; else player = CWorld::Players[playerIndex].m_pPed; if (modelIndex == MI_PICKUP_ADRENALINE) { player->m_bAdrenalineActive = true; player->m_nAdrenalineTime = CTimer::GetTimeInMilliseconds() + 20000; player->m_fCurrentStamina = player->m_fMaxStamina; DMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0); return true; } else if (modelIndex == MI_PICKUP_BODYARMOUR) { player->m_fArmour = CWorld::Players[playerIndex].m_nMaxArmour; DMAudio.PlayFrontEndSound(SOUND_PICKUP_ARMOUR, 0); return true; } else if (modelIndex == MI_PICKUP_INFO) { DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); return true; } else if (modelIndex == MI_PICKUP_HEALTH) { player->m_fHealth = CWorld::Players[playerIndex].m_nMaxHealth; DMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0); return true; } else if (modelIndex == MI_PICKUP_BONUS) { DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); return true; } else if (modelIndex == MI_PICKUP_BRIBE) { int32 level = Max(FindPlayerPed()->m_pWanted->m_nWantedLevel - 1, 0); player->SetWantedLevel(level); DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); return true; } else if (modelIndex == MI_PICKUP_KILLFRENZY) { DMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0); return true; } return false; } void CPickups::RemovePickUp(int32 pickupIndex) { int32 index = GetActualPickupIndex(pickupIndex); if (index == -1) return; if (aPickUps[index].m_pObject) { CWorld::Remove(aPickUps[index].m_pObject); delete aPickUps[index].m_pObject; aPickUps[index].m_pObject = nil; } if (aPickUps[index].m_pExtraObject) { CWorld::Remove(aPickUps[index].m_pExtraObject); delete aPickUps[index].m_pExtraObject; aPickUps[index].m_pExtraObject = nil; } aPickUps[index].m_eType = PICKUP_NONE; aPickUps[index].m_bRemoved = true; } int32 CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity, uint32 rate, bool highPriority, char* pText) { bool bFreeFound = false; int32 slot = 0; if (type == PICKUP_FLOATINGPACKAGE || type == PICKUP_NAUTICAL_MINE_INACTIVE || highPriority) { for (slot = NUMPICKUPS-1; slot >= 0; slot--) { if (aPickUps[slot].m_eType == PICKUP_NONE) { bFreeFound = true; break; } } } if (!bFreeFound) { for (slot = 0; slot < NUMGENERALPICKUPS; slot++) { if (aPickUps[slot].m_eType == PICKUP_NONE) { bFreeFound = true; break; } } } if (!bFreeFound) { for (slot = 0; slot < NUMGENERALPICKUPS; slot++) { if (aPickUps[slot].m_eType == PICKUP_MONEY) break; } if (slot >= NUMGENERALPICKUPS) { for (slot = 0; slot < NUMGENERALPICKUPS; slot++) { if (aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT || aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT_SLOW) break; } if (slot >= NUMGENERALPICKUPS) return -1; aPickUps[slot].GetRidOfObjects(); } } if (slot >= NUMPICKUPS) return -1; aPickUps[slot].m_eType = (ePickupType)type; aPickUps[slot].m_bRemoved = false; aPickUps[slot].m_nQuantity = quantity; aPickUps[slot].m_nMoneySpeed = rate; aPickUps[slot].m_fRevenue = 0.0f; aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds(); aPickUps[slot].m_bWasAmmoCollected = highPriority; aPickUps[slot].m_bWasControlMessageShown = false; if (type == PICKUP_ONCE_TIMEOUT) aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 20000; else if (type == PICKUP_ONCE_TIMEOUT_SLOW) aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 120000; else if (type == PICKUP_MONEY) aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 30000; else if (type == PICKUP_MINE_INACTIVE || type == PICKUP_MINE_ARMED) { aPickUps[slot].m_eType = PICKUP_MINE_INACTIVE; aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500; } else if (type == PICKUP_NAUTICAL_MINE_INACTIVE || type == PICKUP_NAUTICAL_MINE_ARMED) { aPickUps[slot].m_eType = PICKUP_NAUTICAL_MINE_INACTIVE; aPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500; } aPickUps[slot].m_eModelIndex = modelIndex; if (pText) strncpy(aPickUps[slot].m_sTextKey, pText, 8); else aPickUps[slot].m_sTextKey[0] = '\0'; aPickUps[slot].m_vecPos = pos; aPickUps[slot].m_pObject = aPickUps[slot].GiveUsAPickUpObject(&aPickUps[slot].m_pObject, &aPickUps[slot].m_pExtraObject, -1, -1); if (aPickUps[slot].m_pObject) CWorld::Add(aPickUps[slot].m_pObject); if (aPickUps[slot].m_pExtraObject) CWorld::Add(aPickUps[slot].m_pExtraObject); return GetNewUniquePickupIndex(slot); } int32 CPickups::GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity) { return GenerateNewOne(pos, ModelForWeapon(weaponType), type, quantity); } int32 CPickups::GetNewUniquePickupIndex(int32 slot) { if (aPickUps[slot].m_nIndex >= 0xFFFE) aPickUps[slot].m_nIndex = 1; else aPickUps[slot].m_nIndex++; return slot | (aPickUps[slot].m_nIndex << 16); } int32 CPickups::ModelForWeapon(eWeaponType weaponType) { return CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId; } eWeaponType CPickups::WeaponForModel(int32 model) { if (model == MI_PICKUP_BODYARMOUR) return WEAPONTYPE_ARMOUR; if (model == MI_PICKUP_HEALTH) return WEAPONTYPE_HEALTH; if (model == MI_PICKUP_ADRENALINE) return WEAPONTYPE_ARMOUR; if (model == -1) return WEAPONTYPE_UNARMED; return ((CWeaponModelInfo*)CModelInfo::GetModelInfo(model))->GetWeaponInfo(); } void CPickups::AddToCollectedPickupsArray(int32 index) { aPickUpsCollected[CollectedPickUpIndex++] = index | (aPickUps[index].m_nIndex << 16); if (CollectedPickUpIndex >= NUMCOLLECTEDPICKUPS) CollectedPickUpIndex = 0; } void CPickups::Update() { #ifdef FIX_BUGS // RIP speedrunning (solution from SA) if (CReplay::IsPlayingBack()) return; #endif #ifdef CAMERA_PICKUP if ( bPickUpcamActivated ) // taken from PS2 { float dist = Distance2D(StaticCamCoors, FindPlayerCoors()); float mult; if ( dist < 10.0f ) mult = 1.0f - (dist / 10.0f ); else mult = 0.0f; CVector pos = StaticCamCoors; pos.z += (pPlayerVehicle->GetColModel()->boundingBox.GetSize().z + 2.0f) * mult; if ( (CTimer::GetTimeInMilliseconds() - StaticCamStartTime) > 750 ) { TheCamera.SetCamPositionForFixedMode(pos, CVector(0.0f, 0.0f, 0.0f)); TheCamera.TakeControl(FindPlayerVehicle(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_SCRIPT); } if ( FindPlayerVehicle() != pPlayerVehicle || Distance(StaticCamCoors, FindPlayerCoors()) > 40.0f || ((CTimer::GetTimeInMilliseconds() - StaticCamStartTime) > 60000) ) { TheCamera.RestoreWithJumpCut(); bPickUpcamActivated = false; } } #endif if (CPad::GetPad(0)->CollectPickupJustDown()) CollectPickupBuffer = 6; else CollectPickupBuffer = Max(0, CollectPickupBuffer - 1); if (PlayerOnWeaponPickup) PlayerOnWeaponPickup = Max(0, PlayerOnWeaponPickup - 1); #define PICKUPS_FRAME_SPAN (6) #ifdef FIX_BUGS for (uint32 i = NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN) / PICKUPS_FRAME_SPAN; i < NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1) / PICKUPS_FRAME_SPAN; i++) { #else // BUG: this code can only reach 318 out of 320 pickups for (uint32 i = NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN); i < NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1); i++) { #endif if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) AddToCollectedPickupsArray(i); } #undef PICKUPS_FRAME_SPAN for (uint32 i = NUMGENERALPICKUPS; i < NUMPICKUPS; i++) { if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus)) AddToCollectedPickupsArray(i); } } CPickup* CPickups::FindPickUpForThisObject(CEntity *object) { for (uint32 i = 0; i < NUMPICKUPS; i++) { if (aPickUps[i].m_eType != PICKUP_NONE && (aPickUps[i].m_pObject == object || aPickUps[i].m_pExtraObject == object)) { return &aPickUps[i]; } } return &aPickUps[0]; } void CPickups::DoPickUpEffects(CEntity *entity) { CPickup *pickup = FindPickUpForThisObject(entity); if (entity->GetModelIndex() == MI_PICKUP_KILLFRENZY) entity->bDoNotRender = CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame; if (!entity->bDoNotRender) { float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800)); float modifiedSin = 0.3f * (s + 1.0f); #ifdef FIX_BUGS int16 colorId = 0; #else int16 colorId; #endif bool doInnerGlow = false; bool doOuterGlow = true; if (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA) { colorId = WEAPONTYPE_TOTALWEAPONS; doInnerGlow = true; doOuterGlow = false; } else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR) { colorId = WEAPONTYPE_ARMOUR; } else if (entity->GetModelIndex() == MI_PICKUP_BRIBE) { doInnerGlow = true; doOuterGlow = false; } else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY) { doInnerGlow = true; doOuterGlow = false; } else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS) { colorId = WEAPONTYPE_HEALTH; doInnerGlow = true; doOuterGlow = false; } else if (entity->GetModelIndex() == MI_PICKUP_PROPERTY) { doInnerGlow = true; doOuterGlow = false; } else if (entity->GetModelIndex() == MI_PICKUP_PROPERTY_FORSALE) { doInnerGlow = true; doOuterGlow = false; } else if (entity->GetModelIndex() == MI_PICKUP_REVENUE) { doInnerGlow = true; doOuterGlow = false; } else if (entity->GetModelIndex() == MI_PICKUP_SAVEGAME) { doInnerGlow = true; doOuterGlow = false; } else if (entity->GetModelIndex() == MI_PICKUP_CLOTHES) { colorId = WEAPONTYPE_TOTALWEAPONS; doOuterGlow = false; doInnerGlow = true; } else colorId = WeaponForModel(entity->GetModelIndex()); const CVector& pos = pickup->m_vecPos; if (doOuterGlow) { bool corona1 = false; bool corona2 = false; int timerVal = (CTimer::GetTimeInMilliseconds() >> 9) & 7; if (timerVal < 3) corona1 = false; else if (timerVal == 3) corona1 = (CGeneral::GetRandomNumber() & 3) != 0; else corona1 = true; timerVal = (timerVal - 1) & 7; if (timerVal < 3) corona2 = false; else if (timerVal == 3) corona2 = (CGeneral::GetRandomNumber() & 3) != 0; else corona2 = true; if (((CObject*)entity)->bAmmoCollected) { corona2 = false; corona1 = false; } if (corona1) { CCoronas::RegisterCorona((uintptr)entity, aPickupColors[colorId].r * 0.45f, aPickupColors[colorId].g * 0.45f, aPickupColors[colorId].b * 0.45f, 255, pos, 0.76f, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f, false, -0.4f); CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0, aPickupColors[colorId].r * 0.3f, aPickupColors[colorId].g * 0.3f, aPickupColors[colorId].b * 0.3f, 4.0f, 1.0f, 40.0f, false, 0.0f); float radius = (CGeneral::GetRandomNumber() & 0xF) * 0.1f + 3.0f; CPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), radius, aPickupColors[colorId].r / 256.0f, aPickupColors[colorId].g / 256.0f, aPickupColors[colorId].b / 256.0f, CPointLights::FOG_NONE, true); } else CCoronas::RegisterCorona((uintptr)entity, 0, 0, 0, 255, pos, 0.57f, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); if (corona2) { CCoronas::RegisterCorona( (uintptr)entity + 1, aPickupColors[colorId].r * 0.55f, aPickupColors[colorId].g * 0.55f, aPickupColors[colorId].b * 0.55f, 255, pos, 0.6f, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f, false, -0.4f); if (!corona1) CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0, aPickupColors[colorId].r * 0.25f, aPickupColors[colorId].g * 0.25f, aPickupColors[colorId].b * 0.25f, 4.0f, 1.0f, 40.0f, false, 0.0f); } else CCoronas::RegisterCorona((uintptr)entity + 1, 0, 0, 0, 255, pos, 0.45f, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); } CObject *object = (CObject*)entity; if (object->bPickupObjWithMessage || object->bOutOfStock || object->m_nBonusValue || object->m_nCostValue) { float dist = Distance2D(pos, TheCamera.GetPosition()); const float MAXDIST = 14.0f; if (dist < MAXDIST && NumMessages < NUMPICKUPMESSAGES) { RwV3d vecOut; float fDistX, fDistY; if (CSprite::CalcScreenCoors(entity->GetPosition() + CVector(0.0f, 0.0f, 0.7f), &vecOut, &fDistX, &fDistY, true)) { aMessages[NumMessages].m_pos.x = vecOut.x; aMessages[NumMessages].m_pos.y = vecOut.y; aMessages[NumMessages].m_dist.x = fDistX; aMessages[NumMessages].m_dist.y = fDistY; aMessages[NumMessages].m_weaponType = WeaponForModel(entity->GetModelIndex()); aMessages[NumMessages].m_color.red = aPickupColors[colorId].r; aMessages[NumMessages].m_color.green = aPickupColors[colorId].g; aMessages[NumMessages].m_color.blue = aPickupColors[colorId].b; aMessages[NumMessages].m_color.alpha = (1.0f - dist / MAXDIST) * 128.0f; aMessages[NumMessages].m_bOutOfStock = object->bOutOfStock; aMessages[NumMessages].m_quantity = object->m_nBonusValue; aMessages[NumMessages].money = object->m_nCostValue; NumMessages++; } } } uint32 model = entity->GetModelIndex(); CColModel *colModel = entity->GetColModel(); CVector colLength = colModel->boundingBox.max - colModel->boundingBox.min; float maxDimension = Max(colLength.x, Max(colLength.y, colLength.z)); float scale = (Max(1.f, 1.2f / maxDimension) - 1.0f) * 0.6f + 1.0f; if (model == MI_MINIGUN || model == MI_MINIGUN2) scale = 1.2f; entity->GetMatrix().SetRotateZOnlyScaled((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800), scale); if (entity->GetModelIndex() == MI_MINIGUN2) { CMatrix matrix1; CMatrix matrix2; // unused entity->SetPosition(pickup->m_vecPos); matrix1.SetRotateX(0.0f); matrix1.Rotate(DEGTORAD(4.477f), DEGTORAD(-29.731f), DEGTORAD(-1.064f)); matrix1.Translate(CVector(0.829f, -0.001f, 0.226f)); entity->GetMatrix() *= matrix1; } if (doOuterGlow) { CVector scale(0.0f, 0.0f, 0.0f); if (colLength.x == maxDimension) scale.x = colLength.x; else if (colLength.y == maxDimension) scale.y = colLength.y; else scale.z = colLength.z; for (int i = 0; i < 4; i++) { CVector pos = entity->GetMatrix() * (scale * ((float)i / 3.0f)); CCoronas::RegisterCorona( (uintptr)entity + 8 + i, aPickupColors[colorId].r * 0.15f, aPickupColors[colorId].g * 0.15f, aPickupColors[colorId].b * 0.15f, 255, pos, 1.0f, 65.0f, CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); } } if (doInnerGlow) CCoronas::RegisterCorona( #ifdef FIX_BUGS (uintptr)entity + 8 + 4, #else (uintptr)entity + 9, #endif 126, 69, 121, 255, entity->GetPosition(), 1.2f, 50.0f, CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f); } } void CPickups::DoMineEffects(CEntity *entity) { const CVector &pos = entity->GetPosition(); float dist = Distance(pos, TheCamera.GetPosition()); const float MAXDIST = 20.0f; if (dist < MAXDIST) { float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x1FF) * DEGTORAD(360.0f / 0x200)); int32 red = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 64.0f; CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0, red, 0, 0, 4.0f, 1.0f, 40.0f, false, 0.0f); CCoronas::RegisterCorona((uintptr)entity, red, 0, 0, 255, pos, 0.6f, 60.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); } entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x3FF) * DEGTORAD(360.0f / 0x400)); } void CPickups::DoMoneyEffects(CEntity *entity) { const CVector &pos = entity->GetPosition(); float dist = Distance(pos, TheCamera.GetPosition()); const float MAXDIST = 20.0f; if (dist < MAXDIST) { float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x3FF) * DEGTORAD(360.0f / 0x400)); int32 green = (MAXDIST - dist) * (0.2f * s + 0.3f) / MAXDIST * 64.0f; CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0, 0, green, 0, 4.0f, 1.0f, 40.0f, false, 0.0f); CCoronas::RegisterCorona((uintptr)entity, 0, green, 0, 255, pos, 0.4f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); } entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800)); } void CPickups::DoCollectableEffects(CEntity *entity) { const CVector &pos = entity->GetPosition(); float dist = Distance(pos, TheCamera.GetPosition()); const float MAXDIST = 14.0f; if (dist < MAXDIST) { float s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800)); int32 color = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 255.0f; CShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0, color, color, color, 4.0f, 1.0f, 40.0f, false, 0.0f); CCoronas::RegisterCorona((uintptr)entity, color, color, color, 255, pos, 0.6f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f); } entity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0xFFF) * DEGTORAD(360.0f / 0x1000)); } void CPickups::RenderPickUpText() { wchar *strToPrint; for (int32 i = 0; i < NumMessages; i++) { if (aMessages[i].money != 0) { sprintf(gString, "$%d", aMessages[i].money); AsciiToUnicode(gString, gUString); strToPrint = gUString; } else { switch (aMessages[i].m_quantity) // could use some enum maybe { case 0: if (aMessages[i].m_weaponType == WEAPONTYPE_HEALTH || aMessages[i].m_weaponType == WEAPONTYPE_ARMOUR) { strToPrint = nil; } else { if (aMessages[i].m_bOutOfStock) strToPrint = TheText.Get("STOCK"); else { sprintf(gString, "$%d", CostOfWeapon[aMessages[i].m_weaponType]); AsciiToUnicode(gString, gUString); strToPrint = gUString; } } break; case 1: strToPrint = TheText.Get("OUTFT1"); break; case 2: strToPrint = TheText.Get("OUTFT2"); break; case 3: strToPrint = TheText.Get("OUTFT3"); break; case 4: strToPrint = TheText.Get("OUTFT4"); break; case 5: strToPrint = TheText.Get("OUTFT5"); break; case 6: strToPrint = TheText.Get("OUTFT6"); break; case 7: strToPrint = TheText.Get("OUTFT7"); break; case 8: strToPrint = TheText.Get("OUTFT8"); break; case 9: strToPrint = TheText.Get("OUTFT9"); break; case 10: strToPrint = TheText.Get("OUTFT10"); break; case 11: strToPrint = TheText.Get("OUTFT11"); break; case 12: strToPrint = TheText.Get("OUTFT12"); break; case 13: strToPrint = TheText.Get("OUTFT13"); break; default: break; } } if (strToPrint == nil) continue; CFont::SetPropOn(); CFont::SetBackgroundOff(); #ifdef FIX_BUGS const float MAX_SCALE = SCREEN_WIDTH / DEFAULT_SCREEN_WIDTH; #else const float MAX_SCALE = RsGlobal.width / DEFAULT_SCREEN_WIDTH; #endif float fScaleY = aMessages[i].m_dist.y / 30.0f; if (fScaleY > MAX_SCALE) fScaleY = MAX_SCALE; float fScaleX = aMessages[i].m_dist.x / 30.0f; if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE; CFont::SetScale(fScaleX, fScaleY); CFont::SetCentreOn(); CFont::SetCentreSize(SCREEN_WIDTH); CFont::SetJustifyOff(); CFont::SetColor(CRGBA(aMessages[i].m_color.red, aMessages[i].m_color.green, aMessages[i].m_color.blue, aMessages[i].m_color.alpha)); CFont::SetBackGroundOnlyTextOff(); CFont::SetFontStyle(FONT_STANDARD); CFont::PrintString(aMessages[i].m_pos.x, aMessages[i].m_pos.y, strToPrint); } NumMessages = 0; } void CPickups::CreateSomeMoney(CVector pos, int money) { bool found; int pickupCount = Min(money / 20 + 1, 7); int moneyPerPickup = money / pickupCount; for (int i = 0; i < pickupCount; i++) { // (CGeneral::GetRandomNumber() % 256) * PI / 128 gives a float up to something TWOPI-ish. pos.x += 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128); pos.y += 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128); pos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &found) + 0.5f; if (found) { CPickups::GenerateNewOne(CVector(pos.x, pos.y, pos.z), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 3)); } } } void CPickups::RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo(eWeaponType weaponType) { uint32 weaponSlot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot; if (IsWeaponSlotAmmoMergeable(weaponSlot)) { for (int slot = 0; slot < NUMPICKUPS; slot++) { if (aPickUps[slot].m_eType == PICKUP_ONCE || aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT || aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT_SLOW) { if (aPickUps[slot].m_pObject) { if (CWeaponInfo::GetWeaponInfo(WeaponForModel(aPickUps[slot].m_pObject->GetModelIndex()))->m_nWeaponSlot == weaponSlot && aPickUps[slot].m_nQuantity == 0) { CWorld::Remove(aPickUps[slot].m_pObject); delete aPickUps[slot].m_pObject; aPickUps[slot].m_bRemoved = true; aPickUps[slot].m_pObject = nil; aPickUps[slot].m_eType = PICKUP_NONE; } } } } } } void CPickups::DetonateMinesHitByGunShot(CVector *vec1, CVector *vec2) { for (int i = 0; i < NUMGENERALPICKUPS; i++) { if (aPickUps[i].m_eType == PICKUP_NAUTICAL_MINE_ARMED) aPickUps[i].ProcessGunShot(vec1, vec2); } } void CPickups::Load(uint8 *buf, uint32 size) { INITSAVEBUF for (int32 i = 0; i < NUMPICKUPS; i++) { aPickUps[i] = ReadSaveBuf(buf); if (aPickUps[i].m_eType != PICKUP_NONE) { if (aPickUps[i].m_pObject != nil) aPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((uintptr)aPickUps[i].m_pObject - 1); if (aPickUps[i].m_pExtraObject != nil) aPickUps[i].m_pExtraObject = CPools::GetObjectPool()->GetSlot((uintptr)aPickUps[i].m_pExtraObject - 1); } } CollectedPickUpIndex = ReadSaveBuf(buf); ReadSaveBuf(buf); NumMessages = 0; for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++) aPickUpsCollected[i] = ReadSaveBuf(buf); VALIDATESAVEBUF(size) } void CPickups::Save(uint8 *buf, uint32 *size) { *size = sizeof(aPickUps); *size += sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected); INITSAVEBUF for (int32 i = 0; i < NUMPICKUPS; i++) { CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]); if (buf_pickup->m_eType != PICKUP_NONE) { if (buf_pickup->m_pObject != nil) buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex(buf_pickup->m_pObject) + 1); if (buf_pickup->m_pExtraObject != nil) buf_pickup->m_pExtraObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex(buf_pickup->m_pExtraObject) + 1); } } WriteSaveBuf(buf, CollectedPickUpIndex); WriteSaveBuf(buf, (uint16)0); // possibly was NumMessages for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++) WriteSaveBuf(buf, aPickUpsCollected[i]); VALIDATESAVEBUF(*size) } void CPacManPickup::Update() { } int32 CollectGameState; int16 ThingsToCollect; CPacManPickup CPacManPickups::aPMPickUps[NUMPACMANPICKUPS]; CVector CPacManPickups::LastPickUpCoors; int32 CPacManPickups::PillsEatenInRace; bool CPacManPickups::bPMActive; void CPacManPickups::Init() { } void CPacManPickups::Update() { } void CPacManPickups::GeneratePMPickUps(CVector pos, float scrambleMult, int16 count, uint8 type) { } // diablo porn mission pickups static const CVector aRacePoints1[] = { CVector(913.62219f, -155.13692f, 4.9699469f), CVector(913.92401f, -124.12943f, 4.9692569f), CVector(913.27899f, -93.524231f, 7.4325991f), CVector(912.60852f, -63.15905f, 7.4533591f), CVector(934.22144f, -42.049122f, 7.4511471f), CVector(0.0f, 0.0f, 0.0f), }; void CPacManPickups::GeneratePMPickUpsForRace(int32 race) { } void CPacManPickups::GenerateOnePMPickUp(CVector pos) { } void CPacManPickups::Render() { } void CPacManPickups::ClearPMPickUps() { } void CPacManPickups::StartPacManRace(int32 race) { } void CPacManPickups::StartPacManRecord() { } uint32 CPacManPickups::QueryPowerPillsEatenInRace() { return 0; } void CPacManPickups::ResetPowerPillsEatenInRace() { } void CPacManPickups::CleanUpPacManStuff() { } void CPacManPickups::StartPacManScramble(CVector pos, float scrambleMult, int16 count) { } uint32 CPacManPickups::QueryPowerPillsCarriedByPlayer() { return 0; } void CPacManPickups::ResetPowerPillsCarriedByPlayer() { }