class "PsyAntennaPP" (effector) function PsyAntennaPP:__init() super(1001,10000000) self.params = effector_params(); end function PsyAntennaPP:process(pp) pp:assign (self.params); effector.process(self,pp); return true; end class "PsyAntenna" pa_phase={ phIdle = 0, phStarting = 1, phWorking = 2, phStopping = 3 } function PsyAntenna:__init () -- ---------------------------------------------------------------------------------------- -- settings -- ---------------------------------------------------------------------------------------- -- phantom gen -- ---------------------------------------------------------------------------------------- self.phantom_max = 0 --8 --10 --max phantoms self.phantom_spawn_probability = 0.1; -- spawn probability (0..1) self.phantom_spawn_radius = 30.0; -- average radius 30.0m +-15m self.phantom_spawn_height = 2.5 --3 -- average height from actor pos +-1.5m -- antenna self.hit_amplitude = 1.0; -- hit_amplitude*hit_factor.a -- pause time [from]=to self.idle_time = {}; self.idle_time[20] = 21; -- ---------------------------------------------------------------------------------------- -- postprocess -- ---------------------------------------------------------------------------------------- self.base_amplitude = color(0.2,0.15,0.0); -- max base color diff [0.0-0.5] self.gray_amplitude = 0.5; -- gray max intensity [0.0-1.0] self.add_factor = 0.1; --0.3 -- factor * color_animator(RGB) [0.0-1.0] self.dual_amplitude = 0.075 --0.05 -- H&V same [0.0-0.2] self.gray_color = color(0.33,0.33,0.33); -- RGB [0.0-1.0] self.noise_var = noise(0.9,0.3,30); -- intensity, grain, fps [0.0-1.0,0.0-1.0,1-100] -- ---------------------------------------------------------------------------------------- -- class variables initialize self.phase = pa_phase.phIdle; self.power_factor = fcolor(); self.eff_time = 0; self.starting_anim = color_animator ("levels\\psy_antenna\\starting"); self.starting_time = self.starting_anim:length (); self.working_anim = color_animator ("levels\\psy_antenna\\working"); self.stopping_anim = color_animator ("levels\\psy_antenna\\stopping"); self.stopping_time = self.stopping_anim:length(); self.hit_time = 0; self.intensity = 0; self.pp = PsyAntennaPP(); self.pp:start (); end function PsyAntenna:__finalize () self.pp:finish (); end; g_PsyAntenna = PsyAntenna(); function PsyAntenna:construct () end function PsyAntenna:load (packet) set_save_marker(packet, "load", false, "psy_antenna") self.phase = packet:r_u32() set_save_marker(packet, "load", true, "psy_antenna") end function PsyAntenna:save (packet) set_save_marker(packet, "save", false, "psy_antenna") packet:r_u32 (self.phase) set_save_marker(packet, "save", true, "psy_antenna") end function PsyAntenna:is_idle_time (tm) if tm>=13 and tm<14 then return true; elseif tm>=20 and tm<21 then return true; end; return false; end function PsyAntenna:update_postprocess () self.pp.params.color_base = color(0.5+self.base_amplitude.r*self.intensity,0.5+self.base_amplitude.g*self.intensity,0.5+self.base_amplitude.b*self.intensity); self.pp.params.color_gray = color(self.gray_color.r,self.gray_color.g,self.gray_color.b); self.pp.params.color_add = color(self.power_factor.r*self.add_factor,self.power_factor.g*self.add_factor,self.power_factor.b*self.add_factor); self.pp.params.gray = self.gray_amplitude*self.intensity; self.pp.params.dual = duality(self.dual_amplitude*self.power_factor.a,self.dual_amplitude*self.power_factor.a); -- self.pp.params.noise = self.noise_var; end function PsyAntenna:update_psy_hit (dt) local d_time = time_global()-self.hit_time; if d_time>200 and self.power_factor.a>0.01 then self.hit_time = time_global(); local psy_hit = hit(); psy_hit.power = self.power_factor.a*self.hit_amplitude; psy_hit.direction = vector():set( 0, 0, 0 ); psy_hit.impulse = 0; psy_hit.draftsman = db.actor; psy_hit.type = hit.telepatic; db.actor:hit (psy_hit); end; end function PsyAntenna:generate_phantoms () if self.power_factor.a>0.1 then if math.random()self.starting_time then self:switch_to_phase (pa_phase.phWorking); else self.power_factor:set (self.starting_anim:calculate(self.eff_time/1000)); end; end function PsyAntenna:phase_working () self.intensity = 1.0; local h = level.get_time_hours(); if self:is_idle_time(h) then self:switch_to_phase (pa_phase.phStopping); else self.power_factor:set (self.working_anim:calculate(self.eff_time/1000)); self:generate_phantoms (); end; end function PsyAntenna:phase_stopping () self.intensity = 1.0-self.eff_time/self.stopping_time; if self.eff_time>self.stopping_time then self:switch_to_phase (pa_phase.phIdle); else self.power_factor:set (self.stopping_anim:calculate(self.eff_time/1000)); end; end function PsyAntenna:phase_idle () local h = level.get_time_hours(); if false==self:is_idle_time(h) then self:switch_to_phase (pa_phase.phStarting); end; end function PsyAntenna:update (dt) self.eff_time = self.eff_time + dt; if self.phase==pa_phase.phStarting then self:phase_starting (); elseif self.phase==pa_phase.phWorking then self:phase_working (); elseif self.phase==pa_phase.phStopping then self:phase_stopping (); elseif self.phase==pa_phase.phIdle then self:phase_idle (); end; if (self.intensity<0.0) then self.intensity=0.0; end; if (self.intensity>1.0) then self.intensity=1.0; end; self:update_postprocess (); self:update_psy_hit (dt); end function main() while db.actor==nil do wait(); end; if false==has_alife_info("psy_antenna_off") then g_PsyAntenna:construct (); local prev_time = time_global(); while 1 do wait (); local dt = time_global()-prev_time; prev_time = time_global(); g_PsyAntenna:update (dt); end end end