/* =============================================================================== LIGHTNING.HC MG Lightning and Sunbeam effects, and thunderstorm =============================================================================== */ void smolder_think () { vector ofs; ofs_x=random(-10,10); ofs_y=random(-10,10); particle(self.origin+ofs, '0 0 100', random(272,288), random(1,10)); if(random()<0.1&&random()<0.5) CreateWhiteSmoke(self.origin,'0 0 8',HX_FRAME_TIME * 2); thinktime self : 0.1; if(time>self.lifetime) remove(self); } void smolder (vector org) { newmis=spawn(); setorigin(newmis,org); newmis.effects=EF_NODRAW; newmis.lifetime=time+7; newmis.think=smolder_think; thinktime newmis : 0; } void shock_think() { if (self.skin ==0) self.skin = 1; else self.skin = 0; self.scale-=0.1; thinktime self : 0.05; if(time>self.lifetime||self.scale<=0.1) remove(self); } void spawnshockball (vector org) { newmis=spawn(); newmis.drawflags(+)MLS_TORCH; setmodel (newmis, "models/vorpshok.mdl"); setorigin(newmis, org); newmis.lifetime=time+1; newmis.angles_z=90; newmis.think=shock_think; thinktime newmis : 0; newmis.scale=2.5; } /* ================= LightningDamage ================= */ void (vector endpos) ThroughWaterZap = { entity waterloser, attacker; float damg; waterloser = spawn(); setorigin (waterloser, endpos); if(self.classname=="mjolnir") damg=128; else damg=666*2; attacker=self; if(self.classname!="player") if(self.owner.classname=="player") attacker=self.owner; else if(self.controller.classname=="player") attacker=self.controller; T_RadiusDamageWater (waterloser, self, damg,self); remove (waterloser); }; void (vector startpos) ThroughWater = { vector endpos; float mover; mover = 600; while (mover) { mover = mover - 10; endpos = startpos + v_forward * mover; if (pointcontents(endpos) == CONTENT_WATER || pointcontents(endpos) == CONTENT_SLIME) ThroughWaterZap(endpos); else if (pointcontents(endpos) == CONTENT_SOLID) return; } }; void do_lightning_dam (entity from, float damage, string type) { vector loser_org; if((trace_ent.classname=="monster_eidolon"||trace_ent.classname=="obj_chaos_orb")&&type=="lightning") return; if (type != "cubebeam") particle (trace_endpos, '0 0 100', 225, damage*4); if(type=="lightning") spawnshockball((trace_ent.absmax+trace_ent.absmin)*0.5); loser_org=trace_ent.origin; T_Damage (trace_ent, from, from, damage); if(trace_ent.health<=0) smolder(loser_org); if(type=="lightning") sound(trace_ent,CHAN_AUTO,"misc/lighthit.wav",1,ATTN_NORM); else if (type != "cubebeam") sound(trace_ent,CHAN_AUTO,"crusader/sunhit.wav",1,ATTN_NORM); } void(vector p1, vector p2, entity from, float damage,string type) LightningDamage = { entity e1, e2;// swap; vector f; float inertia;//absorb; f = p2 - p1; normalize (f); f_x = 0 - f_y; f_y = f_x; f_z = 0; f = f*16; e1 = e2 = world; traceline (p1, p2, FALSE, self); if(type=="lightning"&&(pointcontents(trace_endpos) == CONTENT_WATER || pointcontents(trace_endpos) == CONTENT_SLIME)) ThroughWaterZap(trace_endpos); else if(type=="lightning"&&(trace_ent.watertype == CONTENT_WATER || trace_ent.watertype == CONTENT_SLIME)) T_RadiusDamageWater (self, self, 666*2,self); else if(self.classname=="mjolnir"&&trace_ent==self.controller) bprint(PRINT_MEDIUM, ""); else if (trace_ent.takedamage) { if (trace_ent.mass<=10) inertia=1; else inertia = trace_ent.mass/10; do_lightning_dam(from,damage,type); if (self.classname=="mjolnir"&&(trace_ent.flags&FL_ONGROUND)&&type=="lightning") { trace_ent.velocity_z = trace_ent.velocity_z + 400/inertia; trace_ent.flags(-)FL_ONGROUND; } } else if(type=="lightning") ThroughWater(p1); e1 = trace_ent; traceline (p1 + f, p2 + f, FALSE, self); if(self.classname=="mjolnir"&&trace_ent==self.controller) bprint(PRINT_MEDIUM, ""); else if(trace_ent != e1 && trace_ent.takedamage) do_lightning_dam(from,damage,type); e2 = trace_ent; traceline (p1 - f, p2 - f, FALSE, self); if(self.classname=="mjolnir"&&trace_ent==self.controller) bprint(PRINT_MEDIUM, ""); else if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage) do_lightning_dam(from,damage,type); }; void do_lightning (entity lowner,float tag, float lflags, float duration, vector spot1, vector spot2, float ldamg,float te_type) { vector damage_dir; WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, te_type); WriteEntity (MSG_BROADCAST, lowner); WriteByte (MSG_BROADCAST, tag+lflags); WriteByte (MSG_BROADCAST, duration); WriteCoord (MSG_BROADCAST, spot1_x); WriteCoord (MSG_BROADCAST, spot1_y); WriteCoord (MSG_BROADCAST, spot1_z); WriteCoord (MSG_BROADCAST, spot2_x); WriteCoord (MSG_BROADCAST, spot2_y); WriteCoord (MSG_BROADCAST, spot2_z); if(ldamg) { if(self.owner.classname=="player") lowner=self.owner; else if(self.controller.classname=="player") lowner=self.controller; damage_dir=normalize(spot2-spot1); LightningDamage (spot1-damage_dir*15, spot2+damage_dir*15, lowner, ldamg,"lightning"); } } void(float max_strikes, float damg) CastLightning = { //Not working, I want 3 seperate beams, when get that, drop damage to 10 vector org, dir,tospot; float number_strikes; self.effects(+)EF_MUZZLEFLASH; if(max_strikes==0) max_strikes=1; while(max_strikes>number_strikes) { if(random()<0.7) sound(self.enemy,CHAN_AUTO,"crusader/lghtn1.wav",1,ATTN_NORM); else sound(self.enemy,CHAN_AUTO,"crusader/lghtn2.wav",1,ATTN_NORM); if(self.enemy.solid==SOLID_BSP&&self.enemy.origin=='0 0 0') org=(self.enemy.absmin+self.enemy.absmax)*0.5; else { org=self.enemy.origin; org_z += 0.5*self.enemy.maxs_z; } dir=org; dir_x+= random(-300,300); dir_y+= random(-300,300); dir_z+= 500; traceline(org,dir,TRUE,self); tospot=org; org=trace_endpos; do_lightning (self,number_strikes,0,4,org,tospot,damg,TE_STREAM_LIGHTNING); number_strikes+=1; } }; void()rolling_thunder; void thunder_clear () { self.owner.aflag-=1; remove(self); } void thunder_sound () { float sound_vol; sound_vol=self.lightvalue2/25; if(sound_vol>1) sound_vol=1; else if(sound_vol<0) sound_vol=0.1; sound (self, CHAN_VOICE, "ambience/thunder1.wav", sound_vol, ATTN_NORM); thinktime self : 5; self.think=thunder_clear; } void spawn_thunder () { self.aflag+=1; newmis=spawn(); self.angles_y=random(360); makevectors(self.angles); setorigin(newmis,self.origin+v_forward*self.lightvalue2*10); newmis.owner=self; newmis.lightvalue2=self.lightvalue2; newmis.think=thunder_sound; thinktime newmis : 2.5 - self.lightvalue2/10; } void flash_wait () { lightstylestatic(self.style,self.lightvalue1); self.think=rolling_thunder; thinktime self : 0; } void lightning_strike (void) { vector org,tospot, lightn_dir; float dist, num_branches; dist=random(self.frags); self.angles_y=random(360); makevectors(self.angles); traceline(self.origin,self.origin+v_forward*dist,TRUE,self); org=trace_endpos; tospot=org-'0 0 1000'; traceline(org,tospot,TRUE,self); tospot=trace_endpos; tospot_x+=random(-100,100); tospot_y+=random(-100,100); dist=vlen(tospot-org); newmis=spawn(); setorigin(newmis,org); if(random()<0.5) sound(newmis,CHAN_AUTO,"crusader/lghtn1.wav",1,ATTN_NORM); else sound(newmis,CHAN_AUTO,"crusader/lghtn2.wav",1,ATTN_NORM); newmis.think=SUB_Remove; thinktime newmis : 3; num_branches = rint(random(3,7)); while(num_branches) { self.level+=1; if(self.level>=8) self.level=0; if (self.lockentity.classname == "monster_buddha") do_lightning (self.lockentity,self.level,STREAM_ATTACHED,4,org,tospot,50,TE_STREAM_LIGHTNING); else do_lightning (self,self.level,STREAM_ATTACHED,4,org,tospot,10000,TE_STREAM_LIGHTNING); lightn_dir=normalize(tospot-org); org=org + lightn_dir*random(num_branches+dist/10,num_branches+dist/5);//Include trace_fraction? tospot=org-'0 0 1000'; traceline(trace_endpos,tospot,TRUE,self); tospot=trace_endpos; if(random()<0.5) tospot_x+=random(125,375); else tospot_x-=random(125,375); if(random()<0.5) tospot_y+=random(125,375); else tospot_y-=random(125,375); /*if(trace_fraction<0.01) { dprint("not into ground\n"); num_branches=0; } else*/ num_branches-=1; } } void rolling_thunder (void) { if(random(100)>=self.wait) { if(self.spawnflags&1&&random(100)