initial commit

This commit is contained in:
2021-10-24 15:36:18 -04:00
commit b9a5a8fe23
11982 changed files with 220468 additions and 0 deletions

View File

@@ -0,0 +1,399 @@
if CPortalSpawnerV2 == nil then
CPortalSpawnerV2 = class({})
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:constructor( szSpawnerNameInput, szLocatorNameInput, nPortalHealthInput, flSummonTimeInput, flScaleInput, rgUnitsInfoInput, bInvulnerableInput )
self.szSpawnerName = szSpawnerNameInput
self.szLocatorName = szLocatorNameInput
self.rgUnitsInfo = rgUnitsInfoInput
self.nPortalHealth = nPortalHealthInput
self.flSummonTime = flSummonTimeInput
if bInvulnerableInput == nil then
self.bInvulnerable = false
else
self.bInvulnerable = bInvulnerableInput
end
self.flScale = flScaleInput
self.vFocusPosition = nil
self.flFocusRadius = nil
self.rgSpawners = {}
self.rgSpawnedPortals = {}
self.Encounter = nil
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:GetSpawnerType()
return "CPortalSpawnerV2"
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:Precache( context )
PrecacheUnitByNameSync( "npc_aghsfort_dark_portal_v2", context, -1 )
PrecacheResource( "particle", "particles/units/heroes/heroes_underlord/abyssal_underlord_darkrift_target.vpcf", context )
PrecacheResource( "particle", "particles/portals/portal_ground_spawn_endpoint.vpcf", context )
for _,rgUnitInfo in pairs ( self.rgUnitsInfo ) do
PrecacheUnitByNameSync( rgUnitInfo.EntityName, context, -1 )
end
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:OnEncounterLoaded( EncounterInput )
--print( "CPortalSpawnerV2:OnEncounterLoaded called for " .. self.szSpawnerName )
self.Encounter = EncounterInput
self.rgSpawners = self.Encounter:GetRoom():FindAllEntitiesInRoomByName( self.szLocatorName, false )
if #self.rgSpawners == 0 then
print( "Failed to find entity " .. self.szSpawnerName .. " as spawner position in map " .. self.Encounter:GetRoom():GetMapName() )
end
ListenToGameEvent( "entity_killed", Dynamic_Wrap( CPortalSpawnerV2, 'OnEntityKilled' ), self )
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:GetSpawnPositionCount()
return #self.rgSpawners
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:GetSpawnPositions()
return self.rgSpawners
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:GetSpawnCountPerSpawnPosition()
local nCount = 0
for _,rgUnitInfo in pairs ( self.rgUnitsInfo ) do
nCount = nCount + rgUnitInfo.Count
end
return nCount
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:SetSpawnInfo( vMins, vMaxs, vEndPos )
self.vMins = vMins
self.vMaxs = vMaxs
self.vEndPos = vEndPos
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:SetSpawnFocus( vCenter, flRadius )
self.vFocusPosition = vCenter
self.flFocusRadius = flRadius
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:SpawnSingleUnitType( rgUnitInfo, vLocation )
local hSpawnedUnits = {}
for i=1,rgUnitInfo.Count do
local vSpawnPos = vLocation
if rgUnitInfo.PositionNoise ~= nil then
local nAttempts = 0
while nAttempts < 16 do
local vTestPos = vSpawnPos + RandomVector( RandomFloat( 0.0, rgUnitInfo.PositionNoise ) )
vTestPos.z = GetGroundHeight( vTestPos, nil )
if GridNav:CanFindPath( vTestPos, vLocation ) then
vSpawnPos = vTestPos
break
end
nAttempts = nAttempts + 1
end
end
local hUnit = CreateUnitByName( rgUnitInfo.EntityName, vSpawnPos, true, nil, nil, rgUnitInfo.Team )
if hUnit == nil then
print( "ERROR! Failed to spawn unit named " .. rgUnitInfo.EntityName )
else
hUnit.bPortalUnit = true
hUnit:FaceTowards( vLocation )
if rgUnitInfo.PostSpawn ~= nil then
rgUnitInfo.PostSpawn( hUnit )
end
table.insert( hSpawnedUnits, hUnit )
end
end
return hSpawnedUnits
end
--------------------------------------------------------------------------------
function CPortalSpawnerV2:TrySpawningPortalUnits()
local hSpawnedUnits={}
local hActivatedPortals={}
for i=#self.rgSpawnedPortals,1,-1 do
local hPortal = self.rgSpawnedPortals[i]
if hPortal ~= nil then
if hPortal.bStartedSound == false and ( hPortal.flSpawnTime - GameRules:GetGameTime() ) <= 6 then
hPortal.bStartedSound = true
EmitSoundOn( "Aghsfort_DarkPortal.StartSummon", hPortal )
end
if hPortal.flSpawnTime <= GameRules:GetGameTime() then
local nSpawned = 0
local vLocation = hPortal:GetAbsOrigin()
for _,rgUnitInfo in pairs ( self.rgUnitsInfo ) do
local hSingleSpawnedUnits = self:SpawnSingleUnitType( rgUnitInfo, vLocation )
for _,hUnit in pairs ( hSingleSpawnedUnits ) do
table.insert( hSpawnedUnits, hUnit )
end
end
table.insert( hActivatedPortals, hPortal )
--printf( "%s spawning %d units", self.szSpawnerName, nSpawned )
end
end
end
if #hSpawnedUnits > 0 then
self.Encounter:OnSpawnerFinished( self, hSpawnedUnits )
end
-- Once a portal has been spawned, it can die
for i=#hActivatedPortals,1,-1 do
local hPortal = hActivatedPortals[i]
StopSoundOn( "Aghsfort_DarkPortal.StartSummon", hPortal )
EmitSoundOn( "Aghsfort_DarkPortal.Complete", hPortal )
self:RemoveSpawnedPortal( hPortal )
self:DestroyPortal( hPortal )
UTIL_Remove( hPortal )
end
return hSpawnedUnits
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:SpawnPortal( hPortalEnt )
hPortalEnt:SetTeam( DOTA_TEAM_BADGUYS )
hPortalEnt:SetMaxHealth( self.nPortalHealth )
hPortalEnt:SetBaseMaxHealth( self.nPortalHealth )
hPortalEnt:Heal( self.nPortalHealth, nil )
hPortalEnt:AddNewModifier( hPortalEnt, nil, "modifier_provide_vision", { duration = -1 } )
hPortalEnt:AddNewModifier( hPortalEnt, nil, "modifier_magic_immune", { duration = -1 } )
hPortalEnt:AddNewModifier( hPortalEnt, nil, "modifier_phased", { duration = -1 } )
hPortalEnt:SetAbsScale( self.flScale )
hPortalEnt.flSpawnTime = GameRules:GetGameTime() + self.flSummonTime
hPortalEnt.bStartedSound = false
-- hPortalEnt.nAmbientFX = ParticleManager:CreateParticle( "particles/units/heroes/heroes_underlord/abyssal_underlord_darkrift_target.vpcf", PATTACH_OVERHEAD_FOLLOW, hPortalEnt )
-- ParticleManager:SetParticleControlEnt( hPortalEnt.nAmbientFX , 1, hPortalEnt, PATTACH_POINT_FOLLOW, "attach_hitloc", hPortalEnt:GetAbsOrigin(), true )
-- ParticleManager:SetParticleControlEnt( hPortalEnt.nAmbientFX , 6, hPortalEnt, PATTACH_ABSORIGIN_FOLLOW, nil, hPortalEnt:GetAbsOrigin(), true )
-- ParticleManager:SetParticleControl( hPortalEnt.nAmbientFX , 10, Vector( 30, 30, 30 ) );
if self.bInvulnerable == true then
-- invulnerable portals make the portal invisible and place an effect on the ground
hPortalEnt:AddEffects( EF_NODRAW )
hPortalEnt.nWarningFX = ParticleManager:CreateParticle( "particles/portals/portal_ground_spawn_endpoint.vpcf", PATTACH_WORLDORIGIN, nil )
ParticleManager:SetParticleControl( hPortalEnt.nWarningFX, 0, hPortalEnt:GetAbsOrigin() )
else
-- vulnerable portals need to remove the invulnerable modifier that's built in to the building
hPortalEnt:RemoveModifierByName( "modifier_invulnerable" )
hPortalEnt.nWarningFX = ParticleManager:CreateParticle( "particles/units/heroes/heroes_underlord/abyssal_underlord_darkrift_target.vpcf", PATTACH_OVERHEAD_FOLLOW, hPortalEnt )
ParticleManager:SetParticleControlEnt( hPortalEnt.nWarningFX, 1, hPortalEnt, PATTACH_POINT_FOLLOW, "attach_hitloc", hPortalEnt:GetAbsOrigin(), true )
ParticleManager:SetParticleControlEnt( hPortalEnt.nWarningFX, 6, hPortalEnt, PATTACH_ABSORIGIN_FOLLOW, nil, hPortalEnt:GetAbsOrigin(), true )
ParticleManager:SetParticleControl( hPortalEnt.nWarningFX, 10, Vector( self.flSummonTime*0.9, self.flSummonTime*0.9, self.flSummonTime*0.9 ) );
end
if self.flSummonTime <= 6 then
hPortalEnt.bStartedSound = true
EmitSoundOn( "Aghsfort_DarkPortal.StartSummon", hPortalEnt )
end
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:DestroyPortal( hPortal )
if hPortal.nWarningFX ~= nil then
ParticleManager:DestroyParticle( hPortal.nWarningFX, false )
hPortal.nWarningFX = nil
end
-- if hVictim.nAmbientFX ~= nil then
-- ParticleManager:DestroyParticle( hPortal.nAmbientFX, false )
-- hPortal.nAmbientFX = nil
-- end
StopSoundOn( "Aghsfort_DarkPortal.StartSummon", hPortal )
EmitSoundOnLocationWithCaster( hPortal:GetAbsOrigin(), "Aghsfort_DarkPortal.Cancel", hPortal )
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:ComputeSpawnerWeights( )
if self.vFocusPosition == nil then
return nil
end
-- Ok, focus position. Means we're going to preferentially pick
-- spawn positions nearer to the spawn focus position
local flTotalWeight = 0.0
for i=1,#self.rgSpawners do
local flDist = ( self.rgSpawners[i]:GetAbsOrigin() - self.vFocusPosition ):Length2D()
local flWeight = math.exp( -0.5 * flDist * flDist / ( self.flFocusRadius * self.flFocusRadius ) )
self.rgSpawners[i].flFocusWeight = flWeight
flTotalWeight = flTotalWeight + flWeight
end
return flTotalWeight
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:RandomlySelectSpawner( Spawners, flTotalSpawnerWeight )
if flTotalSpawnerWeight == nil then
return math.random( 1, #Spawners )
end
-- Ok, focus position. Means we're going to preferentially pick
-- spawn positions close to the focus position.
-- We've already computed weights in ComputeSpawnerWeights
local flValue = RandomFloat( 0, flTotalSpawnerWeight )
local flWeight = 0
for i=1,#Spawners do
flWeight = flWeight + Spawners[i].flFocusWeight
if flValue < flWeight then
return i
end
end
return #Spawners
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:SpawnUnitsFromRandomSpawners( nSpawners )
--print( "spawning from " .. nSpawners .. " " .. self.szSpawnerName .. " spawers out of " .. #self.rgSpawners )
local hAllSpawnedUnits = {}
local Spawners = nil
local flTotalSpawnerWeight = self:ComputeSpawnerWeights( )
for n=1,nSpawners do
if Spawners == nil or #Spawners == 0 then
Spawners = deepcopy( self.rgSpawners )
end
local nIndex = self:RandomlySelectSpawner( Spawners, flTotalSpawnerWeight )
local Spawner = Spawners[ nIndex ]
if Spawner == nil then
print ( "ERROR! CPortalSpawnerV2:SpawnUnitsFromRandomSpawners went WRONG!!!!!!!!!!!!!" )
else
if flTotalSpawnerWeight ~= nil then
flTotalSpawnerWeight = flTotalSpawnerWeight - Spawner.flFocusWeight
end
local vLocation = Spawner:GetAbsOrigin()
local portalTable =
{
MapUnitName = "npc_aghsfort_dark_portal_v2",
origin = tostring( vLocation.x ) .. " " .. tostring( vLocation.y ) .. " " .. tostring( vLocation.z ),
StatusHealth = self.nPortalHealth,
teamnumber = DOTA_TEAM_BADGUYS,
modelscale = self.flScale,
}
local hPortal = CreateUnitFromTable( portalTable, vLocation )
self:SpawnPortal( hPortal )
table.insert( hAllSpawnedUnits, hPortal )
table.insert( self.rgSpawnedPortals, hPortal )
end
table.remove( Spawners, nIndex )
end
return hAllSpawnedUnits
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:RemoveSpawnedPortal( hPortal )
for i=#self.rgSpawnedPortals,1,-1 do
if self.rgSpawnedPortals[i] == hPortal then
table.remove( self.rgSpawnedPortals, i )
return true
end
end
return false
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:OnEntityKilled( event )
local hVictim = nil
if event.entindex_killed ~= nil then
hVictim = EntIndexToHScript( event.entindex_killed )
end
if hVictim == nil or hVictim:IsRealHero() then
return
end
if self:RemoveSpawnedPortal( hVictim ) == true then
if self.Encounter ~= nil then
local hAttacker = nil
if event.entindex_attacker ~= nil then
hAttacker = EntIndexToHScript( event.entindex_attacker )
end
self.Encounter:OnPortalV2Killed( hVictim, hAttacker, self:GetSpawnCountPerSpawnPosition() )
end
self:DestroyPortal( hVictim )
end
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:GetPortalUnitCount( event )
return #self.rgSpawnedPortals
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:GetSpawnerName()
return self.szSpawnerName
end
----------------------------------------------------------------------------
function CPortalSpawnerV2:GetLocatorName()
return self.szLocatorName
end