--[[const char *CCurrencyPackCustom::GetDefaultPowerupModel( void ) { // Custom packs should always be set to a value by hand Assert( m_nAmount > 0 ); // Try to pick a model that's appropriate to our drop amount (which is in our multiplier) if ( m_nAmount >= 25 ) return "models/items/currencypack_large.mdl"; if ( m_nAmount >= 10 ) return "models/items/currencypack_medium.mdl"; return "models/items/currencypack_small.mdl"; } ]] local CURRENCY_DEBUG_MODE = false local DESPAWN_TIME = 30 local TEAM_WHICH_CAN_COLLECT_CASH = TEAM_RED local objectiveResource local mvmStats local function getCurrencyPackModel(currency) if currency >= 25 then return "models/items/currencypack_large.mdl" end if currency >= 10 then return "models/items/currencypack_medium.mdl" end return "models/items/currencypack_small.mdl" end function DistributeMoney(currency) for _, player in pairs(ents.GetAllPlayers()) do if player:IsRealPlayer() then player:AddCurrency(currency) end end -- add to wave & mission stat local vscript = 'NetProps.SetPropInt(activator, "m_currentWaveStats.nCreditsAcquired", NetProps.GetPropInt(activator, "m_currentWaveStats.nCreditsAcquired") + %s)' mvmStats:RunScriptCode(vscript:format(currency), mvmStats, mvmStats) end function UpdateWorldMoneyCount() if not objectiveResource then objectiveResource = ents.FindByClass("tf_objective_resource") end local totalMoney = 0 for _, currencyPack in pairs(ents.FindAllByClass("item_currencypack_custom")) do if currencyPack.CurrencyCount and currencyPack.m_bDistributed ~= 1 then totalMoney = totalMoney + currencyPack.CurrencyCount end end if CURRENCY_DEBUG_MODE then util.PrintToChatAll("[DROP-CURRENCY-PACK]: TOTAL WORLD MONEY: " .. tostring(totalMoney)) end objectiveResource.m_nMvMWorldMoney = totalMoney end function DropCurrencyPack(absOrigin, owner, currency, shouldBeRedCash) if not objectiveResource then objectiveResource = ents.FindByClass("tf_objective_resource") end if not objectiveResource or not IsValid(objectiveResource) then util.PrintToChatAll("[DROP-CURRENCY-PACK]: NO tf_objective_resource FOUND") return end if not mvmStats then mvmStats = ents.FindByClass("tf_mann_vs_machine_stats") end if not mvmStats or not IsValid(mvmStats) then util.PrintToChatAll("[DROP-CURRENCY-PACK]: NO tf_mann_vs_machine_stats FOUND") return end local addCreditDroppedVscript = 'NetProps.SetPropInt(activator, "m_currentWaveStats.nCreditsDropped", NetProps.GetPropInt(activator, "m_currentWaveStats.nCreditsDropped") + %s)' ---@diagnostic disable-next-line: undefined-field mvmStats:RunScriptCode(addCreditDroppedVscript:format(currency), mvmStats, mvmStats) local collectableCurrency = currency if shouldBeRedCash then collectableCurrency = 0 DistributeMoney(currency) end local modelPath = getCurrencyPackModel(currency) local fakePack = ents.CreateWithKeys("item_currencypack_custom", {}, false, false) fakePack.PopLuaCurrency = true fakePack.CurrencyCount = currency -- fakePack.m_hOwnerEntity = owner local packInitVscript = 'NetProps.SetPropBool(activator, "m_bDistributed", %s); activator.DispatchSpawn()' ---@diagnostic disable-next-line: undefined-field fakePack:RunScriptCode((packInitVscript):format(shouldBeRedCash), fakePack, fakePack) fakePack:SetAbsOrigin(absOrigin) fakePack:SetModel(modelPath) -- credit to timey for physic vscript local function randomImpulse() local value = math.random(30, 100) / 100 -- 0.3 to 1 if math.random(1, 2) == 1 then value = -value end return value end local impulseX = randomImpulse() local impulseY = randomImpulse() local moveTypeAndImpulseVscript = "local impulse = Vector(%f, %f, 1);activator.SetMoveType(Constants.EMoveType.MOVETYPE_FLYGRAVITY, Constants.EMoveCollide.MOVECOLLIDE_FLY_BOUNCE);activator.SetSolid(Constants.ESolidType.SOLID_BBOX);activator.SetAbsVelocity(impulse * 250)" fakePack:RunScriptCode(moveTypeAndImpulseVscript:format(impulseX, impulseY), fakePack, fakePack) ---@diagnostic disable-next-line: inject-field -- objectiveResource.m_nMvMWorldMoney = objectiveResource.m_nMvMWorldMoney + collectableCurrency timer.Simple(0.015, function() UpdateWorldMoneyCount() end) if CURRENCY_DEBUG_MODE then util.PrintToChatAll("[DROP-CURRENCY-PACK]: SPAWNED CURRENCY PACK WITH VALUE " .. currency) end local manuallyDespawned = false local despawnTimer despawnTimer = timer.Simple(DESPAWN_TIME, function() if not IsValid(fakePack) then return end manuallyDespawned = true fakePack:Remove() timer.Simple(0.015, function() UpdateWorldMoneyCount() end) end) local removedCallback removedCallback = fakePack:AddCallback(ON_REMOVE, function() -- if CURRENCY_DEBUG_MODE then -- util.PrintToChatAll("[DROP-CURRENCY-PACK]: REMOVED PACK WITH AMOUNT " .. tostring(currency)) -- end pcall(function() timer.Stop(despawnTimer) end) if manuallyDespawned then return end if objectiveResource.m_bMannVsMachineBetweenWaves == true then return end if shouldBeRedCash then return end -- trigger_hurt collection DistributeMoney(currency) timer.Simple(0.015, function() UpdateWorldMoneyCount() end) end) local collected = false local touchedCallback touchedCallback = fakePack:AddCallback(ON_TOUCH, function(_thisEnt, other) if collected then return end if not other:IsPlayer() then return end if other.m_iTeamNum ~= TEAM_WHICH_CAN_COLLECT_CASH then return end collected = true ---@diagnostic disable-next-line: missing-parameter fakePack:RemoveCallback(touchedCallback) fakePack:RemoveCallback(removedCallback) ---@diagnostic disable-next-line: inject-field -- objectiveResource.m_nMvMWorldMoney = objectiveResource.m_nMvMWorldMoney - collectableCurrency manuallyDespawned = true pcall(function() timer.Stop(despawnTimer) end) timer.Simple(0.1, function() if IsValid(fakePack) then fakePack:Remove() end timer.Simple(0.015, function() UpdateWorldMoneyCount() end) end) if shouldBeRedCash then return end if CURRENCY_DEBUG_MODE then util.PrintToChatAll("[DROP-CURRENCY-PACK]: PICKED UP CURRENCY WITH AMOUNT " .. tostring(currency)) end DistributeMoney(currency) end) end