initial commit
This commit is contained in:
383
aghanim_singleplayer/scripts/vscripts/portalspawner.lua
Executable file
383
aghanim_singleplayer/scripts/vscripts/portalspawner.lua
Executable file
@@ -0,0 +1,383 @@
|
||||
if CPortalSpawner == nil then
|
||||
CPortalSpawner = class({})
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:constructor( szSpawnerNameInput, szLocatorNameInput, nPortalHealthInput, flInitialPortalSpawnDelayInput, flInitialSummonTimeInput, flPortalIntervalInput, flScaleInput, rgUnitsInfoInput )
|
||||
self.szSpawnerName = szSpawnerNameInput
|
||||
self.szLocatorName = szLocatorNameInput
|
||||
self.rgUnitsInfo = rgUnitsInfoInput
|
||||
self.nPortalHealth = nPortalHealthInput
|
||||
self.flInitialPortalSpawnDelay = flInitialPortalSpawnDelayInput
|
||||
self.flInitialSummonTime = flInitialSummonTimeInput
|
||||
self.flPortalInterval = flPortalIntervalInput
|
||||
self.flScale = flScaleInput
|
||||
|
||||
self.nNumSpawnsRemaining = 3
|
||||
|
||||
self.Encounter = nil
|
||||
|
||||
self.vLocation = nil
|
||||
self.bHasCreatedPortal = false
|
||||
self.hPortalEnt = nil
|
||||
self.flNextSpawnTime = -1.0
|
||||
self.nWarningFX = nil
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:GetSpawnerType()
|
||||
return "CPortalSpawner"
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:Precache( context )
|
||||
--print( "CPortalSpawner:Precache called for " .. self.szSpawnerName )
|
||||
|
||||
PrecacheUnitByNameSync( "npc_aghsfort_dark_portal", context, -1 )
|
||||
PrecacheResource( "particle", "particles/units/heroes/heroes_underlord/abyssal_underlord_darkrift_target.vpcf", context )
|
||||
PrecacheResource( "particle", "particles/units/heroes/hero_visage/visage_summon_familiars.vpcf", context )
|
||||
|
||||
for _,rgUnitInfo in pairs ( self.rgUnitsInfo ) do
|
||||
PrecacheUnitByNameSync( rgUnitInfo.EntityName, context, -1 )
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:SetLocation( vLocationInput )
|
||||
self.vLocation = vLocationInput
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:OnEncounterLoaded( EncounterInput )
|
||||
--print( "CPortalSpawner:OnEncounterLoaded called for " .. self.szSpawnerName )
|
||||
self.Encounter = EncounterInput
|
||||
|
||||
ListenToGameEvent( "entity_killed", Dynamic_Wrap( CPortalSpawner, 'OnEntityKilled' ), self )
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:Start( flStartTime )
|
||||
self.flNextSpawnTime = GameRules:GetGameTime() + self.flInitialPortalSpawnDelay
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:IsDestroyed()
|
||||
if self.bHasCreatedPortal == false then
|
||||
return false
|
||||
end
|
||||
|
||||
if not self.hPortalEnt or self.hPortalEnt:IsNull() or self.hPortalEnt:IsAlive() == false then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
--[[
|
||||
function CPortalSpawner:GetSpawnCountPerSpawnPosition()
|
||||
|
||||
local nCount = 0
|
||||
for _,rgUnitInfo in pairs ( self.rgUnitsInfo ) do
|
||||
nCount = nCount + rgUnitInfo.Count
|
||||
end
|
||||
return nCount
|
||||
|
||||
end
|
||||
--]]
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:SpawnSingleUnitType( rgUnitInfo )
|
||||
|
||||
local hSpawnedUnits = {}
|
||||
for i=1,rgUnitInfo.Count do
|
||||
|
||||
local vSpawnPos = self.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, self.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 )
|
||||
return nil
|
||||
else
|
||||
hUnit.bPortalUnit = true
|
||||
hUnit:FaceTowards( self.vLocation )
|
||||
if rgUnitInfo.PostSpawn ~= nil then
|
||||
rgUnitInfo.PostSpawn( hUnit )
|
||||
end
|
||||
|
||||
local nFXIndex = ParticleManager:CreateParticle( "particles/units/heroes/hero_visage/visage_summon_familiars.vpcf", PATTACH_CUSTOMORIGIN, hUnit );
|
||||
ParticleManager:SetParticleControl( nFXIndex, 0, hUnit:GetAbsOrigin() );
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 1, hUnit, PATTACH_POINT_FOLLOW, "attach_hitloc", hUnit:GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 2, hUnit, PATTACH_POINT_FOLLOW, "attach_hitloc", hUnit:GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 3, hUnit, PATTACH_POINT_FOLLOW, "attach_hitloc", hUnit:GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( nFXIndex, 4, hUnit, PATTACH_POINT_FOLLOW, "attach_hitloc", hUnit:GetAbsOrigin(), true )
|
||||
ParticleManager:ReleaseParticleIndex( nFXIndex )
|
||||
|
||||
table.insert( hSpawnedUnits, hUnit )
|
||||
end
|
||||
end
|
||||
|
||||
return hSpawnedUnits
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:TrySpawningUnits()
|
||||
--print( "CPortalSpawner:TrySpawningUnits" )
|
||||
|
||||
-- Don't spawn if Start() hasn't been called
|
||||
if self.flNextSpawnTime < 0 then
|
||||
return
|
||||
end
|
||||
|
||||
if self.bHasCreatedPortal == false then
|
||||
local flTimeReaminingToPortalSpawn = self.flNextSpawnTime - GameRules:GetGameTime()
|
||||
|
||||
if flTimeReaminingToPortalSpawn <= 0 then
|
||||
--print( "Portal named " .. self:GetSpawnerName() .. " spawning portal!" )
|
||||
self:SpawnPortal()
|
||||
end
|
||||
end
|
||||
|
||||
if self.bHasCreatedPortal == false then
|
||||
return
|
||||
end
|
||||
|
||||
if self.hPortalEnt ~= nil and self.hPortalEnt:IsNull() == false and self.hPortalEnt:IsAlive() then
|
||||
local flTimeRemaining = self.flNextSpawnTime - GameRules:GetGameTime()
|
||||
--print( "Portal named " .. self:GetSpawnerName() .. " has " .. flTimeRemaining .. " time remaining till spawn." )
|
||||
|
||||
if flTimeRemaining <= 0 then
|
||||
--print( "Portal named " .. self:GetSpawnerName() .. " is spawning units!" )
|
||||
self:SpawnUnits()
|
||||
if self.nNumSpawnsRemaining > 0 then
|
||||
self.flNextSpawnTime = self.flNextSpawnTime + self.flPortalInterval
|
||||
else
|
||||
self.flNextSpawnTime = -1 -- disabled from here on out
|
||||
end
|
||||
end
|
||||
|
||||
if flTimeRemaining <= 5 and flTimeRemaining > 0 and self.nWarningFX == nil then
|
||||
--print( "Portal named " .. self:GetSpawnerName() .. " creating warning fx and sounds" )
|
||||
|
||||
self.nWarningFX = ParticleManager:CreateParticle( "particles/units/heroes/heroes_underlord/abyssal_underlord_darkrift_target.vpcf", PATTACH_OVERHEAD_FOLLOW, self.hPortalEnt )
|
||||
ParticleManager:SetParticleControlEnt( self.nWarningFX, 1, self.hPortalEnt, PATTACH_POINT_FOLLOW, "attach_hitloc", self.hPortalEnt:GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControlEnt( self.nWarningFX, 6, self.hPortalEnt, PATTACH_ABSORIGIN_FOLLOW, nil, self.hPortalEnt:GetAbsOrigin(), true )
|
||||
ParticleManager:SetParticleControl( self.nWarningFX, 10, Vector( flTimeRemaining*0.9, flTimeRemaining*0.9, flTimeRemaining*0.9 ) );
|
||||
|
||||
EmitSoundOn( "Aghsfort_DarkPortal.StartSummon", self.hPortalEnt )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:SpawnUnits()
|
||||
if self.vLocation == nil then
|
||||
print( "ERROR - Spawner " .. self.szSpawnerName .. " does not have a valid location!" )
|
||||
return
|
||||
end
|
||||
|
||||
local nSpawned = 0
|
||||
|
||||
local hSpawnedUnits = {}
|
||||
|
||||
for _,rgUnitInfo in pairs ( self.rgUnitsInfo ) do
|
||||
local hSingleSpawnedUnits = self:SpawnSingleUnitType( rgUnitInfo )
|
||||
nSpawned = nSpawned + rgUnitInfo.Count
|
||||
|
||||
for _,hUnit in pairs ( hSingleSpawnedUnits ) do
|
||||
table.insert( hSpawnedUnits, hUnit )
|
||||
end
|
||||
end
|
||||
|
||||
--printf( "%s spawning %d units", self.szSpawnerName, nSpawned )
|
||||
|
||||
if self.nWarningFX ~= nil then
|
||||
ParticleManager:DestroyParticle( self.nWarningFX, false )
|
||||
self.nWarningFX = nil
|
||||
end
|
||||
|
||||
EmitSoundOn( "Aghsfort_DarkPortal.Complete", self.hPortalEnt )
|
||||
StopSoundOn( "Aghsfort_DarkPortal.StartSummon", self.hPortalEnt )
|
||||
|
||||
if #hSpawnedUnits > 0 then
|
||||
self.Encounter:OnSpawnerFinished( self, hSpawnedUnits )
|
||||
end
|
||||
|
||||
self.nNumSpawnsRemaining = self.nNumSpawnsRemaining - 1
|
||||
|
||||
if self.nNumSpawnsRemaining <= 0 then
|
||||
self.hPortalEnt:SetSkin( 1 )
|
||||
end
|
||||
|
||||
--[[
|
||||
if self.nNumSpawnsRemaining <= 0 then
|
||||
if self.Encounter ~= nil then
|
||||
local hAttacker = nil
|
||||
self.Encounter:OnPortalKilled( self.hPortalEnt, hAttacker, 0 )
|
||||
end
|
||||
|
||||
self:DestroyPortal( true )
|
||||
end
|
||||
--]]
|
||||
return hSpawnedUnits
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:SpawnPortal()
|
||||
--print( "CPortalSpawner:SpawnPortal" )
|
||||
|
||||
if self.bHasCreatedPortal == true then
|
||||
print( 'ERROR: Trying to spawn a portal named ' .. self.szSpawnerName .. ' but it has already spawned a portal!')
|
||||
return
|
||||
end
|
||||
|
||||
if self.hPortalEnt ~= nil then
|
||||
print( 'ERROR: Trying to spawn a portal named ' .. self.szSpawnerName .. ' but it already has a portal!')
|
||||
return
|
||||
end
|
||||
|
||||
if self.vLocation == nil then
|
||||
print( 'ERROR: Trying to spawn a portal named ' .. self.szSpawnerName .. ' with a nil location!' )
|
||||
return
|
||||
end
|
||||
|
||||
local portalTable =
|
||||
{
|
||||
MapUnitName = "npc_aghsfort_dark_portal",
|
||||
origin = tostring( self.vLocation.x ) .. " " .. tostring( self.vLocation.y ) .. " " .. tostring( self.vLocation.z ),
|
||||
StatusHealth = self.nPortalHealth,
|
||||
teamnumber = DOTA_TEAM_BADGUYS,
|
||||
modelscale = self.flScale,
|
||||
}
|
||||
|
||||
self.hPortalEnt = CreateUnitFromTable( portalTable, self.vLocation )
|
||||
|
||||
self.hPortalEnt:SetTeam( DOTA_TEAM_BADGUYS )
|
||||
self.hPortalEnt:RemoveModifierByName( "modifier_invulnerable" )
|
||||
|
||||
self.hPortalEnt:SetMaxHealth( self.nPortalHealth )
|
||||
self.hPortalEnt:SetBaseMaxHealth( self.nPortalHealth )
|
||||
self.hPortalEnt:Heal( self.nPortalHealth, nil )
|
||||
self.hPortalEnt:AddNewModifier( self.hPortalEnt, nil, "modifier_provide_vision", { duration = -1 } )
|
||||
self.hPortalEnt:AddNewModifier( self.hPortalEnt, nil, "modifier_magic_immune", { duration = -1 } )
|
||||
self.hPortalEnt:AddNewModifier( self.hPortalEnt, nil, "modifier_phased", { duration = -1 } )
|
||||
|
||||
self.hPortalEnt:SetAbsScale( self.flScale )
|
||||
|
||||
self.flNextSpawnTime = GameRules:GetGameTime() + self.flInitialSummonTime
|
||||
|
||||
-- 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 ) );
|
||||
|
||||
-- self.nWarningFX = ParticleManager:CreateParticle( "particles/units/heroes/heroes_underlord/abyssal_underlord_darkrift_target.vpcf", PATTACH_OVERHEAD_FOLLOW, self.hPortalEnt )
|
||||
-- ParticleManager:SetParticleControlEnt( self.nWarningFX, 1, self.hPortalEnt, PATTACH_POINT_FOLLOW, "attach_hitloc", self.hPortalEnt:GetAbsOrigin(), true )
|
||||
-- ParticleManager:SetParticleControlEnt( self.nWarningFX, 6, self.hPortalEnt, PATTACH_ABSORIGIN_FOLLOW, nil, self.hPortalEnt:GetAbsOrigin(), true )
|
||||
-- ParticleManager:SetParticleControl( self.nWarningFX, 10, Vector( self.flNextSpawnTime*0.9, self.flNextSpawnTime*0.9, self.flNextSpawnTime*0.9 ) );
|
||||
|
||||
EmitSoundOn( "Aghsfort_DarkPortal.Created", self.hPortalEnt )
|
||||
|
||||
self.bHasCreatedPortal = true
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner: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 hVictim ~= self.hPortalEnt then
|
||||
return
|
||||
end
|
||||
|
||||
if self.Encounter ~= nil then
|
||||
local hAttacker = nil
|
||||
if event.entindex_attacker ~= nil then
|
||||
hAttacker = EntIndexToHScript( event.entindex_attacker )
|
||||
end
|
||||
|
||||
local nSupressedUnits = 0
|
||||
for _,rgUnitInfo in pairs ( self.rgUnitsInfo ) do
|
||||
nSupressedUnits = nSupressedUnits + ( rgUnitInfo.Count * self.nNumSpawnsRemaining )
|
||||
end
|
||||
|
||||
self.Encounter:OnPortalKilled( hVictim, hAttacker, nSupressedUnits )
|
||||
end
|
||||
|
||||
self:DestroyPortal( false )
|
||||
end
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:DestroyPortal( bRemove )
|
||||
StopSoundOn( "Aghsfort_DarkPortal.StartSummon", self.hPortalEnt )
|
||||
StopSoundOn( "Aghsfort_DarkPortal.Created", self.hPortal )
|
||||
if self.hPortal and not self.hPortal:IsNull() then
|
||||
EmitSoundOnLocationWithCaster( self.hPortal:GetAbsOrigin(), "Aghsfort_DarkPortal.Cancel", self.hPortal )
|
||||
end
|
||||
|
||||
if self.nWarningFX ~= nil then
|
||||
ParticleManager:DestroyParticle( self.nWarningFX, false )
|
||||
self.nWarningFX = nil
|
||||
end
|
||||
|
||||
if bRemove and self.hPortalEnt and not self.hPortalEnt:IsNull() then
|
||||
UTIL_Remove( self.hPortalEnt )
|
||||
self.hPortalEnt = nil
|
||||
end
|
||||
|
||||
-- if hVictim.nAmbientFX ~= nil then
|
||||
-- ParticleManager:DestroyParticle( hPortal.nAmbientFX, false )
|
||||
-- hPortal.nAmbientFX = nil
|
||||
-- end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:GetSpawnerName()
|
||||
return self.szSpawnerName
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:GetLocatorName()
|
||||
return self.szLocatorName
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
function CPortalSpawner:GetNumSpawnsRemaining()
|
||||
return self.nNumSpawnsRemaining
|
||||
end
|
||||
Reference in New Issue
Block a user