Diff
checker
텍스트
텍스트
이미지
문서
Excel
폴더
Legal
Enterprise
데스크톱
요금제
로그인
데스크톱 앱 다운로드
텍스트 비교
두 텍스트 파일의 차이점을 찾아보세요
도구
기록
실시간 편집
변경 없는 행 숨기기
줄바꿈 비활성화
레이아웃
나란히 보기
합쳐 보기
비교 단위
스마트
단어
글자
구문 강조
언어 선택
제외
텍스트 변환
첫 변경으로
수정
Diffchecker Desktop
가장 안전하게 Diffchecker를 사용하는 방법. 데스크톱 앱을 사용하면 비교 데이터가 외부로 전송되지 않습니다!
데스크톱 앱 받기
Untitled diff
생성일
11년 전
비교 결과 만료 없음
초기화
내보내기
공유
설명
16 삭제
행
총
삭제
글자
총
삭제
이 기능을 계속 사용하려면 업그레이드해 주세요
Diff
checker
Pro
요금제 보기
246 행
복사
9 추가
행
총
추가
글자
총
추가
이 기능을 계속 사용하려면 업그레이드해 주세요
Diff
checker
Pro
요금제 보기
239 행
복사
local BaseHassler = Class(function(self, inst)
local BaseHassler = Class(function(self, inst)
self.inst = inst
self.inst = inst
self.warning = false
self.warning = false
self.timetoattack = nil
self.timetoattack = nil
self.warnduration = 60
self.warnduration = 60
self.timetonextwarningsound = 0
self.timetonextwarningsound = 0
self.announcewarningsoundinterval = 4
self.announcewarningsoundinterval = 4
self.hasslerprefab = "deerclops"
self.hasslerprefab = "deerclops"
self.warningsound = "dontstarve/creatures/deerclops/distant"
self.warningsound = "dontstarve/creatures/deerclops/distant"
self.attacksperwinter = 1
self.attacksperwinter = 1
self.attackduringsummer = false
self.attackduringsummer = false
self.attackdelay = nil
self.attackdelay = nil
self.attackrandom = nil
self.attackrandom = nil
복사
복사됨
복사
복사됨
self.inst:ListenForEvent("snowcoverchange", function(inst
)
self.inst:ListenForEvent("snowcoverchange", function(inst
, data)
local snow_cover = GetSeasonManager() and GetSeasonManager():GetSnowPercent() or 0
if
data and data.
snow
>= 0.2 then
if
snow
_cover
>= 0.2 then
if not self.timetoattack then
if not self.timetoattack then
self:StartAttacks()
self:StartAttacks()
end
end
복사
복사됨
복사
복사됨
elseif
snow
_cover
<= 0 and self.attackduringsummer and not self.timetoattack then
elseif
data and data.
snow
<= 0 and self.attackduringsummer and not self.timetoattack then
self:StartAttacks()
self:StartAttacks()
else
else
self:CeaseAttacks()
self:CeaseAttacks()
end
end
end, GetWorld() )
end, GetWorld() )
end)
end)
local HASSLER_SPAWN_DIST = 40
local HASSLER_SPAWN_DIST = 40
local WANDER_AWAY_DIST = 100
local WANDER_AWAY_DIST = 100
function BaseHassler:SetHasslerPrefab(prefab)
function BaseHassler:SetHasslerPrefab(prefab)
self.hasslerprefab = prefab
self.hasslerprefab = prefab
end
end
function BaseHassler:SetWarningSound(sound)
function BaseHassler:SetWarningSound(sound)
self.warningsound = sound
self.warningsound = sound
end
end
function BaseHassler:SetAttacksPerWinter(attacks)
function BaseHassler:SetAttacksPerWinter(attacks)
self.attacksperwinter = attacks
self.attacksperwinter = attacks
end
end
function BaseHassler:SetAttackDuringSummer(attack)
function BaseHassler:SetAttackDuringSummer(attack)
self.attackduringsummer = attack
self.attackduringsummer = attack
end
end
function BaseHassler:OnSave()
function BaseHassler:OnSave()
if not self.noserial then
if not self.noserial then
return
return
{
{
warning = self.warning,
warning = self.warning,
timetoattack = self.timetoattack,
timetoattack = self.timetoattack,
attackdelay = self.attackdelay,
attackdelay = self.attackdelay,
attackrandom = self.attackrandom,
attackrandom = self.attackrandom,
}
}
end
end
self.noserial = false
self.noserial = false
end
end
function BaseHassler:OnLoad(data)
function BaseHassler:OnLoad(data)
self.warning = data.warning or false
self.warning = data.warning or false
self.timetoattack = data.timetoattack
self.timetoattack = data.timetoattack
self.attackdelay = data.attackdelay
self.attackdelay = data.attackdelay
self.attackrandom = data.attackrandom
self.attackrandom = data.attackrandom
if self.timetoattack then
if self.timetoattack then
self.inst:StartUpdatingComponent(self)
self.inst:StartUpdatingComponent(self)
end
end
end
end
function BaseHassler:OnProgress()
function BaseHassler:OnProgress()
self.noserial = true
self.noserial = true
end
end
function BaseHassler:GetDebugString()
function BaseHassler:GetDebugString()
if not self.timetoattack then
if not self.timetoattack then
return "DORMANT"
return "DORMANT"
elseif self.timetoattack > 0 then
elseif self.timetoattack > 0 then
return string.format("%s Deerclops is coming in %2.2f", self.warning and "WARNING" or "WAITING", self.timetoattack)
return string.format("%s Deerclops is coming in %2.2f", self.warning and "WARNING" or "WAITING", self.timetoattack)
else
else
return string.format("ATTACKING!!!")
return string.format("ATTACKING!!!")
end
end
end
end
복사
복사됨
복사
복사됨
function BaseHassler:LongUpdate(dt)
self:OnUpdate(dt)
end
function BaseHassler:OnUpdate(dt)
function BaseHassler:OnUpdate(dt)
if not self.timetoattack then
if not self.timetoattack then
self:CeaseAttacks()
self:CeaseAttacks()
return
return
end
end
self.timetoattack = self.timetoattack - dt
self.timetoattack = self.timetoattack - dt
if self.timetoattack <= 0 then
if self.timetoattack <= 0 then
self.warning = false
self.warning = false
self:ReleaseHassler()
self:ReleaseHassler()
self:CeaseAttacks()
self:CeaseAttacks()
else
else
if not self.warning and self.timetoattack < self.warnduration then
if not self.warning and self.timetoattack < self.warnduration then
self.warning = true
self.warning = true
self.timetonextwarningsound = 0
self.timetonextwarningsound = 0
end
end
end
end
if self.warning then
if self.warning then
self.timetonextwarningsound = self.timetonextwarningsound - dt
self.timetonextwarningsound = self.timetonextwarningsound - dt
if self.timetonextwarningsound <= 0 then
if self.timetonextwarningsound <= 0 then
self.announcewarningsoundinterval = self.announcewarningsoundinterval - 1
self.announcewarningsoundinterval = self.announcewarningsoundinterval - 1
if self.announcewarningsoundinterval <= 0 then
if self.announcewarningsoundinterval <= 0 then
self.announcewarningsoundinterval = 10 + math.random(5)
self.announcewarningsoundinterval = 10 + math.random(5)
복사
복사됨
복사
복사됨
GetPlayer()
.components.talker:Say(GetString(
GetPlayer()
.prefab, "ANNOUNCE_DEERCLOPS"))
self.inst
.components.talker:Say(GetString(
self.inst
.prefab, "ANNOUNCE_DEERCLOPS"))
end
end
local inst = CreateEntity()
local inst = CreateEntity()
inst.entity:AddTransform()
inst.entity:AddTransform()
inst.entity:AddSoundEmitter()
inst.entity:AddSoundEmitter()
inst.persists = false
inst.persists = false
local theta = math.random() * 2 * PI
local theta = math.random() * 2 * PI
local radius = 5
local radius = 5
self.timetonextwarningsound = 15 + math.random(4)
self.timetonextwarningsound = 15 + math.random(4)
if self.timetoattack < 30 then
if self.timetoattack < 30 then
self.timetonextwarningsound = 10 + math.random(1)
self.timetonextwarningsound = 10 + math.random(1)
radius = radius
radius = radius
elseif self.timetoattack < 60 then
elseif self.timetoattack < 60 then
radius = radius + 10
radius = radius + 10
elseif self.timetoattack < 90 then
elseif self.timetoattack < 90 then
radius = radius + 15
radius = radius + 15
else
else
radius = radius + 20
radius = radius + 20
end
end
복사
복사됨
복사
복사됨
local offset = Vector3(
GetPlayer()
.Transform:GetWorldPosition()) + Vector3(radius * math.cos( theta ), 0, -radius * math.sin( theta ))
local offset = Vector3(
self.inst
.Transform:GetWorldPosition()) + Vector3(radius * math.cos( theta ), 0, -radius * math.sin( theta ))
inst.Transform:SetPosition(offset.x,offset.y,offset.z)
inst.Transform:SetPosition(offset.x,offset.y,offset.z)
inst.SoundEmitter:PlaySound(self.warningsound)
inst.SoundEmitter:PlaySound(self.warningsound)
inst:DoTaskInTime(1.5, function() inst:Remove() end)
inst:DoTaskInTime(1.5, function() inst:Remove() end)
end
end
end
end
end
end
function BaseHassler:StartAttacks()
function BaseHassler:StartAttacks()
local timeLeftInSeason = GetSeasonManager():GetDaysLeftInSeason() * TUNING.TOTAL_DAY_TIME
local timeLeftInSeason = GetSeasonManager():GetDaysLeftInSeason() * TUNING.TOTAL_DAY_TIME
if self.attacksperwinter > 0 then
if self.attacksperwinter > 0 then
if self.attacksperwinter < 1 then
if self.attacksperwinter < 1 then
--special case: plan attack for NEXT season
--special case: plan attack for NEXT season
local summersToSkip = math.floor( (1 / self.attacksperwinter) - 1 )
local summersToSkip = math.floor( (1 / self.attacksperwinter) - 1 )
local wintersToSkip = math.max(0, summersToSkip-1)
local wintersToSkip = math.max(0, summersToSkip-1)
self.attackdelay = 0.5*timeLeftInSeason + TUNING.TOTAL_DAY_TIME*(summersToSkip*GetSeasonManager().summerlength + wintersToSkip*GetSeasonManager().winterlength)
self.attackdelay = 0.5*timeLeftInSeason + TUNING.TOTAL_DAY_TIME*(summersToSkip*GetSeasonManager().summerlength + wintersToSkip*GetSeasonManager().winterlength)
self.attackrandom = 0.25*timeLeftInSeason
self.attackrandom = 0.25*timeLeftInSeason
else
else
self.attackdelay = timeLeftInSeason / self.attacksperwinter
self.attackdelay = timeLeftInSeason / self.attacksperwinter
self.attackrandom = 0.25*self.attackdelay
self.attackrandom = 0.25*self.attackdelay
end
end
self:PlanNextAttack()
self:PlanNextAttack()
self.inst:StartUpdatingComponent(self)
self.inst:StartUpdatingComponent(self)
end
end
end
end
function BaseHassler:PlanNextAttack()
function BaseHassler:PlanNextAttack()
if (not GetSeasonManager():IsWinter() and not self.attackduringsummer) or not self.attackdelay then
if (not GetSeasonManager():IsWinter() and not self.attackduringsummer) or not self.attackdelay then
self:CeaseAttacks()
self:CeaseAttacks()
return
return
end
end
self.timetoattack = GetRandomWithVariance(self.attackdelay, self.attackrandom or 0)
self.timetoattack = GetRandomWithVariance(self.attackdelay, self.attackrandom or 0)
end
end
function BaseHassler:CeaseAttacks()
function BaseHassler:CeaseAttacks()
self.timetoattack = nil
self.timetoattack = nil
self.warning = false
self.warning = false
self.inst:StopUpdatingComponent(self)
self.inst:StopUpdatingComponent(self)
end
end
function BaseHassler:GetSpawnPoint(pt)
function BaseHassler:GetSpawnPoint(pt)
local theta = math.random() * 2 * PI
local theta = math.random() * 2 * PI
local radius = HASSLER_SPAWN_DIST
local radius = HASSLER_SPAWN_DIST
local offset = FindWalkableOffset(pt, theta, radius, 12, true)
local offset = FindWalkableOffset(pt, theta, radius, 12, true)
if offset then
if offset then
return pt+offset
return pt+offset
end
end
end
end
function BaseHassler:GetWanderAwayPoint(pt)
function BaseHassler:GetWanderAwayPoint(pt)
local theta = math.random() * 2 * PI
local theta = math.random() * 2 * PI
local radius = WANDER_AWAY_DIST
local radius = WANDER_AWAY_DIST
local ground = GetWorld()
local ground = GetWorld()
-- Walk the circle trying to find a valid spawn point
-- Walk the circle trying to find a valid spawn point
local steps = 12
local steps = 12
for i = 1, 12 do
for i = 1, 12 do
local offset = Vector3(radius * math.cos( theta ), 0, -radius * math.sin( theta ))
local offset = Vector3(radius * math.cos( theta ), 0, -radius * math.sin( theta ))
local wander_point = pt + offset
local wander_point = pt + offset
if ground.Map and ground.Map:GetTileAtPoint(wander_point.x, wander_point.y, wander_point.z) ~= GROUND.IMPASSABLE
if ground.Map and ground.Map:GetTileAtPoint(wander_point.x, wander_point.y, wander_point.z) ~= GROUND.IMPASSABLE
and ground.Pathfinder:IsClear(pt.x, pt.y, pt.z, wander_point.x, wander_point.y, wander_point.z, {ignorewalls = true} ) then
and ground.Pathfinder:IsClear(pt.x, pt.y, pt.z, wander_point.x, wander_point.y, wander_point.z, {ignorewalls = true} ) then
return wander_point
return wander_point
end
end
theta = theta - (2 * PI / steps)
theta = theta - (2 * PI / steps)
end
end
end
end
function BaseHassler:ReleaseHassler()
function BaseHassler:ReleaseHassler()
복사
복사됨
복사
복사됨
local pt = Vector3(
GetPlayer()
.Transform:GetWorldPosition())
local pt = Vector3(
self.inst
.Transform:GetWorldPosition())
local spawn_pt = self:GetSpawnPoint(pt)
local spawn_pt = self:GetSpawnPoint(pt)
if spawn_pt then
if spawn_pt then
local hassler = TheSim:FindFirstEntityWithTag(self.hasslerprefab)
local hassler = TheSim:FindFirstEntityWithTag(self.hasslerprefab)
if not hassler then
if not hassler then
hassler = SpawnPrefab(self.hasslerprefab)
hassler = SpawnPrefab(self.hasslerprefab)
end
end
if hassler then
if hassler then
hassler.Physics:Teleport(spawn_pt:Get())
hassler.Physics:Teleport(spawn_pt:Get())
복사
복사됨
복사
복사됨
local target = GetClosestInstWithTag("structure",
GetPlayer()
, 40)
local target = GetClosestInstWithTag("structure",
self.inst
, 40)
if target then
if target then
local targetPos = Vector3(target.Transform:GetWorldPosition() )
local targetPos = Vector3(target.Transform:GetWorldPosition() )
hassler.components.knownlocations:RememberLocation("targetbase", targetPos)
hassler.components.knownlocations:RememberLocation("targetbase", targetPos)
local wanderAwayPoint = self:GetWanderAwayPoint(targetPos)
local wanderAwayPoint = self:GetWanderAwayPoint(targetPos)
if wanderAwayPoint then
if wanderAwayPoint then
hassler.components.knownlocations:RememberLocation("home", wanderAwayPoint)
hassler.components.knownlocations:RememberLocation("home", wanderAwayPoint)
end
end
else
else
복사
복사됨
복사
복사됨
hassler.components.combat:SetTarget(
GetPlayer()
)
hassler.components.combat:SetTarget(
self.inst
)
end
end
end
end
end
end
end
end
return BaseHassler
return BaseHassler
저장된 비교 결과
원본
파일 열기
local BaseHassler = Class(function(self, inst) self.inst = inst self.warning = false self.timetoattack = nil self.warnduration = 60 self.timetonextwarningsound = 0 self.announcewarningsoundinterval = 4 self.hasslerprefab = "deerclops" self.warningsound = "dontstarve/creatures/deerclops/distant" self.attacksperwinter = 1 self.attackduringsummer = false self.attackdelay = nil self.attackrandom = nil self.inst:ListenForEvent("snowcoverchange", function(inst) local snow_cover = GetSeasonManager() and GetSeasonManager():GetSnowPercent() or 0 if snow_cover >= 0.2 then if not self.timetoattack then self:StartAttacks() end elseif snow_cover <= 0 and self.attackduringsummer and not self.timetoattack then self:StartAttacks() else self:CeaseAttacks() end end, GetWorld() ) end) local HASSLER_SPAWN_DIST = 40 local WANDER_AWAY_DIST = 100 function BaseHassler:SetHasslerPrefab(prefab) self.hasslerprefab = prefab end function BaseHassler:SetWarningSound(sound) self.warningsound = sound end function BaseHassler:SetAttacksPerWinter(attacks) self.attacksperwinter = attacks end function BaseHassler:SetAttackDuringSummer(attack) self.attackduringsummer = attack end function BaseHassler:OnSave() if not self.noserial then return { warning = self.warning, timetoattack = self.timetoattack, attackdelay = self.attackdelay, attackrandom = self.attackrandom, } end self.noserial = false end function BaseHassler:OnLoad(data) self.warning = data.warning or false self.timetoattack = data.timetoattack self.attackdelay = data.attackdelay self.attackrandom = data.attackrandom if self.timetoattack then self.inst:StartUpdatingComponent(self) end end function BaseHassler:OnProgress() self.noserial = true end function BaseHassler:GetDebugString() if not self.timetoattack then return "DORMANT" elseif self.timetoattack > 0 then return string.format("%s Deerclops is coming in %2.2f", self.warning and "WARNING" or "WAITING", self.timetoattack) else return string.format("ATTACKING!!!") end end function BaseHassler:LongUpdate(dt) self:OnUpdate(dt) end function BaseHassler:OnUpdate(dt) if not self.timetoattack then self:CeaseAttacks() return end self.timetoattack = self.timetoattack - dt if self.timetoattack <= 0 then self.warning = false self:ReleaseHassler() self:CeaseAttacks() else if not self.warning and self.timetoattack < self.warnduration then self.warning = true self.timetonextwarningsound = 0 end end if self.warning then self.timetonextwarningsound = self.timetonextwarningsound - dt if self.timetonextwarningsound <= 0 then self.announcewarningsoundinterval = self.announcewarningsoundinterval - 1 if self.announcewarningsoundinterval <= 0 then self.announcewarningsoundinterval = 10 + math.random(5) GetPlayer().components.talker:Say(GetString(GetPlayer().prefab, "ANNOUNCE_DEERCLOPS")) end local inst = CreateEntity() inst.entity:AddTransform() inst.entity:AddSoundEmitter() inst.persists = false local theta = math.random() * 2 * PI local radius = 5 self.timetonextwarningsound = 15 + math.random(4) if self.timetoattack < 30 then self.timetonextwarningsound = 10 + math.random(1) radius = radius elseif self.timetoattack < 60 then radius = radius + 10 elseif self.timetoattack < 90 then radius = radius + 15 else radius = radius + 20 end local offset = Vector3(GetPlayer().Transform:GetWorldPosition()) + Vector3(radius * math.cos( theta ), 0, -radius * math.sin( theta )) inst.Transform:SetPosition(offset.x,offset.y,offset.z) inst.SoundEmitter:PlaySound(self.warningsound) inst:DoTaskInTime(1.5, function() inst:Remove() end) end end end function BaseHassler:StartAttacks() local timeLeftInSeason = GetSeasonManager():GetDaysLeftInSeason() * TUNING.TOTAL_DAY_TIME if self.attacksperwinter > 0 then if self.attacksperwinter < 1 then --special case: plan attack for NEXT season local summersToSkip = math.floor( (1 / self.attacksperwinter) - 1 ) local wintersToSkip = math.max(0, summersToSkip-1) self.attackdelay = 0.5*timeLeftInSeason + TUNING.TOTAL_DAY_TIME*(summersToSkip*GetSeasonManager().summerlength + wintersToSkip*GetSeasonManager().winterlength) self.attackrandom = 0.25*timeLeftInSeason else self.attackdelay = timeLeftInSeason / self.attacksperwinter self.attackrandom = 0.25*self.attackdelay end self:PlanNextAttack() self.inst:StartUpdatingComponent(self) end end function BaseHassler:PlanNextAttack() if (not GetSeasonManager():IsWinter() and not self.attackduringsummer) or not self.attackdelay then self:CeaseAttacks() return end self.timetoattack = GetRandomWithVariance(self.attackdelay, self.attackrandom or 0) end function BaseHassler:CeaseAttacks() self.timetoattack = nil self.warning = false self.inst:StopUpdatingComponent(self) end function BaseHassler:GetSpawnPoint(pt) local theta = math.random() * 2 * PI local radius = HASSLER_SPAWN_DIST local offset = FindWalkableOffset(pt, theta, radius, 12, true) if offset then return pt+offset end end function BaseHassler:GetWanderAwayPoint(pt) local theta = math.random() * 2 * PI local radius = WANDER_AWAY_DIST local ground = GetWorld() -- Walk the circle trying to find a valid spawn point local steps = 12 for i = 1, 12 do local offset = Vector3(radius * math.cos( theta ), 0, -radius * math.sin( theta )) local wander_point = pt + offset if ground.Map and ground.Map:GetTileAtPoint(wander_point.x, wander_point.y, wander_point.z) ~= GROUND.IMPASSABLE and ground.Pathfinder:IsClear(pt.x, pt.y, pt.z, wander_point.x, wander_point.y, wander_point.z, {ignorewalls = true} ) then return wander_point end theta = theta - (2 * PI / steps) end end function BaseHassler:ReleaseHassler() local pt = Vector3(GetPlayer().Transform:GetWorldPosition()) local spawn_pt = self:GetSpawnPoint(pt) if spawn_pt then local hassler = TheSim:FindFirstEntityWithTag(self.hasslerprefab) if not hassler then hassler = SpawnPrefab(self.hasslerprefab) end if hassler then hassler.Physics:Teleport(spawn_pt:Get()) local target = GetClosestInstWithTag("structure", GetPlayer(), 40) if target then local targetPos = Vector3(target.Transform:GetWorldPosition() ) hassler.components.knownlocations:RememberLocation("targetbase", targetPos) local wanderAwayPoint = self:GetWanderAwayPoint(targetPos) if wanderAwayPoint then hassler.components.knownlocations:RememberLocation("home", wanderAwayPoint) end else hassler.components.combat:SetTarget(GetPlayer()) end end end end return BaseHassler
수정본
파일 열기
local BaseHassler = Class(function(self, inst) self.inst = inst self.warning = false self.timetoattack = nil self.warnduration = 60 self.timetonextwarningsound = 0 self.announcewarningsoundinterval = 4 self.hasslerprefab = "deerclops" self.warningsound = "dontstarve/creatures/deerclops/distant" self.attacksperwinter = 1 self.attackduringsummer = false self.attackdelay = nil self.attackrandom = nil self.inst:ListenForEvent("snowcoverchange", function(inst, data) if data and data.snow >= 0.2 then if not self.timetoattack then self:StartAttacks() end elseif data and data.snow <= 0 and self.attackduringsummer and not self.timetoattack then self:StartAttacks() else self:CeaseAttacks() end end, GetWorld() ) end) local HASSLER_SPAWN_DIST = 40 local WANDER_AWAY_DIST = 100 function BaseHassler:SetHasslerPrefab(prefab) self.hasslerprefab = prefab end function BaseHassler:SetWarningSound(sound) self.warningsound = sound end function BaseHassler:SetAttacksPerWinter(attacks) self.attacksperwinter = attacks end function BaseHassler:SetAttackDuringSummer(attack) self.attackduringsummer = attack end function BaseHassler:OnSave() if not self.noserial then return { warning = self.warning, timetoattack = self.timetoattack, attackdelay = self.attackdelay, attackrandom = self.attackrandom, } end self.noserial = false end function BaseHassler:OnLoad(data) self.warning = data.warning or false self.timetoattack = data.timetoattack self.attackdelay = data.attackdelay self.attackrandom = data.attackrandom if self.timetoattack then self.inst:StartUpdatingComponent(self) end end function BaseHassler:OnProgress() self.noserial = true end function BaseHassler:GetDebugString() if not self.timetoattack then return "DORMANT" elseif self.timetoattack > 0 then return string.format("%s Deerclops is coming in %2.2f", self.warning and "WARNING" or "WAITING", self.timetoattack) else return string.format("ATTACKING!!!") end end function BaseHassler:OnUpdate(dt) if not self.timetoattack then self:CeaseAttacks() return end self.timetoattack = self.timetoattack - dt if self.timetoattack <= 0 then self.warning = false self:ReleaseHassler() self:CeaseAttacks() else if not self.warning and self.timetoattack < self.warnduration then self.warning = true self.timetonextwarningsound = 0 end end if self.warning then self.timetonextwarningsound = self.timetonextwarningsound - dt if self.timetonextwarningsound <= 0 then self.announcewarningsoundinterval = self.announcewarningsoundinterval - 1 if self.announcewarningsoundinterval <= 0 then self.announcewarningsoundinterval = 10 + math.random(5) self.inst.components.talker:Say(GetString(self.inst.prefab, "ANNOUNCE_DEERCLOPS")) end local inst = CreateEntity() inst.entity:AddTransform() inst.entity:AddSoundEmitter() inst.persists = false local theta = math.random() * 2 * PI local radius = 5 self.timetonextwarningsound = 15 + math.random(4) if self.timetoattack < 30 then self.timetonextwarningsound = 10 + math.random(1) radius = radius elseif self.timetoattack < 60 then radius = radius + 10 elseif self.timetoattack < 90 then radius = radius + 15 else radius = radius + 20 end local offset = Vector3(self.inst.Transform:GetWorldPosition()) + Vector3(radius * math.cos( theta ), 0, -radius * math.sin( theta )) inst.Transform:SetPosition(offset.x,offset.y,offset.z) inst.SoundEmitter:PlaySound(self.warningsound) inst:DoTaskInTime(1.5, function() inst:Remove() end) end end end function BaseHassler:StartAttacks() local timeLeftInSeason = GetSeasonManager():GetDaysLeftInSeason() * TUNING.TOTAL_DAY_TIME if self.attacksperwinter > 0 then if self.attacksperwinter < 1 then --special case: plan attack for NEXT season local summersToSkip = math.floor( (1 / self.attacksperwinter) - 1 ) local wintersToSkip = math.max(0, summersToSkip-1) self.attackdelay = 0.5*timeLeftInSeason + TUNING.TOTAL_DAY_TIME*(summersToSkip*GetSeasonManager().summerlength + wintersToSkip*GetSeasonManager().winterlength) self.attackrandom = 0.25*timeLeftInSeason else self.attackdelay = timeLeftInSeason / self.attacksperwinter self.attackrandom = 0.25*self.attackdelay end self:PlanNextAttack() self.inst:StartUpdatingComponent(self) end end function BaseHassler:PlanNextAttack() if (not GetSeasonManager():IsWinter() and not self.attackduringsummer) or not self.attackdelay then self:CeaseAttacks() return end self.timetoattack = GetRandomWithVariance(self.attackdelay, self.attackrandom or 0) end function BaseHassler:CeaseAttacks() self.timetoattack = nil self.warning = false self.inst:StopUpdatingComponent(self) end function BaseHassler:GetSpawnPoint(pt) local theta = math.random() * 2 * PI local radius = HASSLER_SPAWN_DIST local offset = FindWalkableOffset(pt, theta, radius, 12, true) if offset then return pt+offset end end function BaseHassler:GetWanderAwayPoint(pt) local theta = math.random() * 2 * PI local radius = WANDER_AWAY_DIST local ground = GetWorld() -- Walk the circle trying to find a valid spawn point local steps = 12 for i = 1, 12 do local offset = Vector3(radius * math.cos( theta ), 0, -radius * math.sin( theta )) local wander_point = pt + offset if ground.Map and ground.Map:GetTileAtPoint(wander_point.x, wander_point.y, wander_point.z) ~= GROUND.IMPASSABLE and ground.Pathfinder:IsClear(pt.x, pt.y, pt.z, wander_point.x, wander_point.y, wander_point.z, {ignorewalls = true} ) then return wander_point end theta = theta - (2 * PI / steps) end end function BaseHassler:ReleaseHassler() local pt = Vector3(self.inst.Transform:GetWorldPosition()) local spawn_pt = self:GetSpawnPoint(pt) if spawn_pt then local hassler = TheSim:FindFirstEntityWithTag(self.hasslerprefab) if not hassler then hassler = SpawnPrefab(self.hasslerprefab) end if hassler then hassler.Physics:Teleport(spawn_pt:Get()) local target = GetClosestInstWithTag("structure", self.inst, 40) if target then local targetPos = Vector3(target.Transform:GetWorldPosition() ) hassler.components.knownlocations:RememberLocation("targetbase", targetPos) local wanderAwayPoint = self:GetWanderAwayPoint(targetPos) if wanderAwayPoint then hassler.components.knownlocations:RememberLocation("home", wanderAwayPoint) end else hassler.components.combat:SetTarget(self.inst) end end end end return BaseHassler
비교하기