/* * $Header: /HexenWorld/Siege/barrel.hc 11 5/31/98 2:58p Mgummelt $ */ /* ============================================================================== BARRELS ============================================================================== */ $cd \art\models\objects\barrel\final $base base 128 128 $skin skin $frame resting //Checks to see if the bounding boxes of the 2 ents overlap at any point. //Not intended for BSP models- bounding box models only float overlapped (entity ent1, entity ent2) { vector mins1,maxs1,mins2,maxs2; float overlapped_axes; mins1=ent1.absmin; maxs1=ent1.absmax; mins2=ent2.absmin; maxs2=ent2.absmax; if(mins1_x>maxs2_x||maxs1_xmaxs2_y||maxs1_ymaxs2_z||maxs1_zCHUNK_MAX) model_cnt=CHUNK_MAX; while (model_cnt>0) { if (chunk_cnt < CHUNK_MAX*2) { CreateModelChunks(space,scalemod); chunk_cnt+=1; } model_cnt-=1; } make_chunk_reset(); self.solid = SOLID_NOT; // self.effects = EF_NODRAW; if(self.trigger_field) remove(self.trigger_field); } void barrel_go (); void rep_barrel_wait () { entity item; //float dist,s1,s2; // dprint("Barrel checking to respawn\n"); item = findradius(self.origin, 256); while (item) { // dprint("Barrel found ents\n"); if (item.solid&&item.solid!=SOLID_TRIGGER&&item.solid!=SOLID_BSP&&item!=self) { // dprint("Barrel found solid\n"); // dist = vhlen(item.origin-self.origin); // s1 = item.maxs_x*1.5; // s2 = 24;//barrel size, at most- 22.6 if 16 by 16 // if(s1+s2>=dist) if(overlapped(self,item)) { // dprint("Barrel waiting- too close to "); // dprint(item.classname); // dprint("\n"); self.think = rep_barrel_wait; thinktime self : 2; return; } } item = item.chain; } barrel_go(); } void spawn_rep_barrel (void) { obj_barrel_fake_chunk_death(); setorigin(self,self.wallspot); self.effects=self.flags=self.flags2=self.frame=self.fire_damage=0; self.enemy=world; self.classname=self.netname; self.flags2(+)FL_SUMMONED; self.angles=self.velocity=self.avelocity='0 0 0'; self.health=self.max_health; self.think=rep_barrel_wait; thinktime self : 0.5; setmodel(self,"models/null.spr"); // dprintv("Barrel respawning with %s angles\n",self.angles); /* entity replacement; replacement=spawn(); replacement.spawnflags=self.spawnflags; setmodel(replacement,"models/null.spr"); setorigin(replacement,self.wallspot); replacement.frags=self.frags; replacement.classname=self.netname; replacement.flags2(+)FL_SUMMONED; replacement.targetname=self.targetname; replacement.think=rep_barrel_wait; replacement.nextthink = time + 1; */ } //BIG FIRE======================================================== void burn_out () { if(self.scale>0.1) { self.scale-=0.1; setsize(self.trigger_field,'-24 -24 0'*self.scale,'24 24 48'*self.scale); thinktime self : 0.01; self.dmg=self.trigger_field.dmg=self.scale*3; } else { remove(self.trigger_field); stopSound(self,0); remove(self); } } void spawn_big_fire(vector org) { entity bigfire,oself; bigfire=spawn(); oself=self; self = bigfire; self.dmg=2; self.classname="big greek fire"; self.drawflags(+)SCALE_ORIGIN_BOTTOM|DRF_TRANSLUCENT|MLS_FIREFLICKER; self.scale = 1; setmodel(self,"models/newfire.mdl"); setorigin(self,org); spawn_burnfield(org); setsize(self.trigger_field,'-48 -48 0','48 48 64'); sound (self,CHAN_UPDATE+PHS_OVERRIDE_R, "misc/flamloop.wav", 0.5, ATTN_LOOP); self.think = burn_out; thinktime self : 30;//burn for 30 seconds self=oself; } //GREEK FIRE======================================================== void obj_barrel_gfire_explode (void) { T_RadiusDamage (self, self, random(150,200), self); WriteByte (MSG_MULTICAST, SVC_TEMPENTITY); WriteByte (MSG_MULTICAST, TE_PURIFY2_EXPLODE); WriteCoord (MSG_MULTICAST, self.origin_x - self.movedir_x * 8); WriteCoord (MSG_MULTICAST, self.origin_y - self.movedir_y * 8); WriteCoord (MSG_MULTICAST, self.origin_z - self.movedir_z * 8); multicast(self.origin,MULTICAST_PHS_R); spawn_big_fire(self.origin); if(self.spawnflags&BARREL_RESPAWN) { spawn_rep_barrel(); // obj_barrel_fake_chunk_death(); return; } remove(self); } //void MakeExplosion(string explodemodel); void()barrel_check_float; /*void obj_barrel_gravity() { local vector slope; if(self.ltime <= time) { slope = getslope(self); if(slope != self.dest) { self.speed = trace_plane_normal_z * 20; self.ideal_yaw = self.dest = trace_plane_normal; } self.ltime = time + 0.4; } thinktime self : 0.05; } */ void float(void) { float x_mod, y_mod, z_mod; vector org; org=self.origin; if(pointcontents(org)==CONTENT_WATER||pointcontents(org)==CONTENT_SLIME||pointcontents(org)==CONTENT_LAVA) { if(self.velocity_x) self.velocity_x/=1.1; if(self.velocity_y) self.velocity_y/=1.1; org_z+= self.maxs_z*0.77;//float only 23% above waterlevel if(pointcontents(org)==CONTENT_WATER||pointcontents(org)==CONTENT_SLIME||pointcontents(org)==CONTENT_LAVA) { // self.flags(+)FL_SWIM; self.flags(-)FL_ONGROUND; if(self.velocity_z<77) self.velocity_z=80; else self.velocity_z+=random(0,0.01); } else { self.velocity_z-=random(0,0.01); } if(random()<0.3) { y_mod=random(-0.15,0.15); if(random()<0.5) self.angles_y+=y_mod; else self.angles_y+=y_mod; } if(random()<0.3) { x_mod=random(-0.15,0.15); if(fabs(self.angles_x+x_mod)>10) self.angles_x-=x_mod; else self.angles_x+=x_mod; } if(random()<0.3) { z_mod=random(-0.15,0.15); if(fabs(self.angles_z+z_mod)>10) self.angles_z-=z_mod; else self.angles_z+=z_mod; } thinktime self : 0.1; } else { self.angles_z=self.angles_z=0; self.classname="barrel"; self.think=barrel_check_float; thinktime self : 0.5; } } void barrel_check_float (void) { vector org; org=self.origin; if(pointcontents(org)==CONTENT_WATER||pointcontents(org)==CONTENT_SLIME||pointcontents(org)==CONTENT_LAVA&&(!self.spawnflags&BARREL_SINK)) { self.classname=="barrel_floating"; self.think=float; thinktime self : 0; } else { self.classname="barrel"; self.think=barrel_check_float; thinktime self : 0.5; } } /* * obj_barrel_explode() -- Blows the barrel up. */ void obj_barrel_explode_go() { entity attacker; if(self.enemy.flags2&FL_ALIVE)//give credit to person who blew it up attacker=self.enemy; else attacker=self; T_RadiusDamage(self, attacker, 200,self);//00, self); // sound(self, CHAN_VOICE, "weapons/explode.wav", 1, ATTN_NORM); particleexplosion(self.origin + '0 0 83',384,60,40); starteffect(CE_LG_EXPLOSION , (self.absmin+self.absmax)*0.5); if(self.spawnflags&BARREL_RESPAWN) { spawn_rep_barrel(); // obj_barrel_fake_chunk_death(); return; } chunk_death(); } void obj_barrel_explode () { //delay so too many don't cause crash self.th_die=SUB_Null; self.takedamage = DAMAGE_NO; self.think=obj_barrel_explode_go; if(dmMode==DM_SIEGE) thinktime self : 0; else thinktime self : random()+0.05; } void obj_barrel_use_explode () {//no delay self.th_die=SUB_Null; self.takedamage = DAMAGE_NO; self.think=obj_barrel_explode_go; thinktime self : 0; } void()monster_rat; void rat_spawn(float offset) { newmis=spawn(); newmis.angles_y=self.angles_y+offset*60; newmis.flags2(+)FL_SUMMONED; if(self.target) newmis.target=self.target; makevectors(newmis.angles); setorigin(newmis,self.origin+v_forward*16); newmis.think=monster_rat; thinktime newmis : 0; } void barrel_die () { self.solid=SOLID_NOT; if(self.model!="models/gfire.mdl") { if(random()<0.3||self.target!=""||self.classname=="monster_ratnest") { float r; r=rint(random(3,6)); while(r>0) { rat_spawn(r); r-=1; } } } else { //particleexplosion(self.origin + '0 0 24',264,60,40); sound(self,CHAN_AUTO,"raven/outwater.wav",1,ATTN_NORM); } if(self.spawnflags&BARREL_RESPAWN) { spawn_rep_barrel(); // obj_barrel_fake_chunk_death(); return; } if(self.classname!="monster_ratnest") chunk_death(); else remove(self); } /* * obj_barrel_slide() -- Slides a barrel in the direction given in self.movedir. */ /* void obj_barrel_slide() { local entity victim; local float direction; //old if function, direction was null // if(walkmove(direction, self.count) == FALSE) if(!walkmove(self.cnt, self.count, FALSE)) { //Is this supposed to push something else it hits? victim = findradius(self.origin, self.count + 38); while(victim) { if(victim.movetype != MOVETYPE_NONE && victim != self) { direction = vectoyaw(victim.origin - self.origin); if(self.cnt <= 60 && direction >= 300) direction -= 360; if(direction > self.cnt - 60 && direction < self.cnt + 60) victim.velocity += (victim.origin - self.origin) * self.count; } victim = victim.chain; } } // if(!self.spawnflags & BARREL_DOWNHILL) // self.count -= 0.7; // if(self.count < 0.5) // self.think = obj_barrel_gravity; //What is this supposed to do? // obj_barrel_gravity(); // reduce self.count to simulate friction, right? self.count = self.count - 1; if(self.count<=0) { self.think=SUB_Null; self.nextthink = -1; } else thinktime self : 0.05; } */ void obj_barrel_roll (void) { self.v_angle_y=self.angles_y; self.v_angle_x=self.v_angle_z=0; makevectors(self.v_angle); self.velocity-=self.movedir*self.speed; self.movedir=normalize(v_forward); self.speed/=1.01; self.anglespeed=self.speed/7.7; if(self.speed<1&&self.speed>-1) { self.velocity = '0 0 0'; self.think = SUB_Null; self.nextthink = -1; } else { vector dircheck; // float hitcheck; //Rolling sound if(self.flags&FL_ONGROUND) { self.flags(-)FL_ONGROUND; self.last_onground=time; self.level=TRUE; } else if(self.level) { self.level=FALSE; self.last_onground = time - 1; self.speed/=2;//slow down if go off cliff, looks weird otherwise } self.velocity+=self.movedir*self.speed; self.angles_x-=self.anglespeed; self.think=obj_barrel_roll; thinktime self : 0.05; dircheck=normalize(self.velocity); makevectors(self.angles); traceline(self.origin,self.origin+dircheck*39,FALSE,self); if(trace_fraction==1) { traceline(self.origin+v_right*16,self.origin+v_right*16+dircheck*39,FALSE,self); if(trace_fraction==1) traceline(self.origin-v_right*16,self.origin-v_right*16+dircheck*39,FALSE,self); } if(trace_fraction<1) { sound(self,CHAN_AUTO,"fx/thngland.wav",1,ATTN_NORM); // landing thud self.speed*=-0.25; self.last_onground=time - 1; obj_fly_hurt(trace_ent); self.velocity=dircheck*self.speed; } } } /* * obj_barrel_shoot() -- Called when a barrel is shot. */ void obj_barrel_shoot() { sound(self,CHAN_AUTO,"fx/thngland.wav",1,ATTN_NORM); // landing thud // if(self.aflag) // return; /* self.movedir = normalize(self.origin - self.enemy.origin); self.velocity=self.velocity + self.movedir*self.count; self.avelocity_y=random(100,300); self.velocity_z=self.velocity_z + 50; if(self.velocity_z>150) self.velocity_z=150; self.flags(-)FL_ONGROUND; */ } /* * obj_barrel_use() -- Called when a barrel is triggered. */ void barrel_drop () { self.movetype=MOVETYPE_FLYMISSILE; // setorigin(self,self.origin - '0 0 20'); self.flags(-)FL_PUSH|FL_ONGROUND; self.velocity='0 0 -200'; self.touch=self.th_die; } void obj_barrel_use() { // if(other.movetype == MOVETYPE_STEP) // obj_pull(); // else obj_barrel_explode(); } void obj_barrel_gfire_light () { self.use=SUB_Null; self.th_die = obj_barrel_gfire_explode; sound (self, CHAN_AUTO, "weapons/expsmall.wav", 1, ATTN_NORM); starteffect(CE_FLOOR_EXPLOSION , self.origin+'0 0 110'); self.frame=1; sound(self,CHAN_UPDATE+PHS_OVERRIDE_R,"misc/flamloop.wav",0.5,ATTN_LOOP); self.effects(+)EF_UPDATESOUND|EF_BRIGHTLIGHT; } void spawn_barrel(float barrel_type) { if(dmMode==DM_SIEGE) self.spawnflags(+)BARREL_RESPAWN; self.frags=barrel_type; if(!self.flags2&FL_SUMMONED) { precache_model("models/barrel.mdl"); if(barrel_type==BARREL_NORMAL) precache_model("models/rat.mdl"); } CreateEntityNew(self,ENT_BARREL,"models/barrel.mdl",chunk_death); if(self.spawnflags&ON_SIDE) { self.aflag=1; self.frame=1; self.v_angle=self.angles; setsize(self, '-18 -13 -13','18 13 13'); self.hull=HULL_CROUCH; } else { setsize(self, '-13 -13 0','13 13 36'); self.hull=HULL_PLAYER; } if (self.scale) self.mass *=self.scale; self.netname=self.classname; self.classname = "barrel"; self.flags(+)FL_PUSH; self.touch = obj_push; self.th_pain = obj_barrel_shoot; if (barrel_type==BARREL_NORMAL) { self.th_die = barrel_die; self.skin=0; } else if (barrel_type==BARREL_INDESTRUCTIBLE) { self.health = 999999; self.th_die = SUB_Null; self.skin=1; } else if (barrel_type==BARREL_EXPLODING) { self.th_die = obj_barrel_explode; self.skin=2; } else if (barrel_type==BARREL_GFIRE) { self.th_die = barrel_die; setmodel(self,"models/gfire.mdl"); setsize(self,'-16 -16 0','16 16 56'); self.hull=HULL_PLAYER; self.use=obj_barrel_gfire_light; } if(!self.spawnflags&BARREL_SINK) { self.think=barrel_check_float; thinktime self : 0; } if(pointcontents(self.origin)!=CONTENT_EMPTY&&(!self.spawnflags&BARREL_SINK)) { self.classname="barrel_floating"; self.think=float; thinktime self : 0; } else if(!self.flags2&FL_SUMMONED&&!self.spawnflags&BARREL_NO_DROP) droptofloor(); if(self.spawnflags&DROP_USE) { self.movetype=MOVETYPE_NONE; self.use=barrel_drop; if(barrel_type==BARREL_EXPLODING) self.th_die=obj_barrel_use_explode; } else if(self.targetname) if(barrel_type==BARREL_EXPLODING) self.use=obj_barrel_use_explode; else self.use=self.th_die; if(self.spawnflags&BARREL_RESPAWN) self.wallspot=self.origin; spawn_push_trigger(3); } /*QUAKED obj_barrel (0.3 0.1 0.6) (-13 -13 0) (13 13 36) DOWNHILL NO_DROP ON_SIDE SINK DROP_USE RESPAWN A barrel, just a plain old barrel -------------------------FIELDS------------------------- .health - How hard it is to smash Default: 25 DOWNHILL - This barrel will slide downhill with gravity. NO_DROP - Will not drop to floor before spawning ON_SIDE - Will make the barrel appear to be on it's side, the top will point right (90 degrees) Note- barrels on their side must be placed at least 13 units above the floor. SINK - Sinks in water DROP_USE - Barrel has no gravity until used, then will drop RESPAWN - Barrel will RESPAWN at it's initial origin when it is destroyed -------------------------------------------------------- */ void obj_barrel(void) { if(self.spawnflags&DROP_USE) self.spawnflags(+)BARREL_NO_DROP; precache_sound("misc/squeak.wav"); if(self.health) self.max_health=self.health; spawn_barrel(BARREL_NORMAL); if(!self.max_health) self.max_health=self.health; self.mass = 75; } /*QUAKED obj_barrel_indestructible (0.3 0.1 0.6) (-13 -13 0) (13 13 36) DOWNHILL NO_DROP ON_SIDE SINK DROP_USE RESPAWN A barrel you just can't break -------------------------FIELDS------------------------- DOWNHILL - This barrel will slide downhill with gravity. NO_DROP - Will not drop to floor before spawning ON_SIDE - Will make the barrel appear to be on it's side, the top will point right (90 degrees) Note- barrels on their side must be placed at least 13 units above the floor. SINK - Sinks in water DROP_USE - Barrel has no gravity until used, then will drop RESPAWN - Barrel will RESPAWN at it's initial origin when it is destroyed -------------------------------------------------------- */ void obj_barrel_indestructible(void) { if(self.spawnflags&DROP_USE) self.spawnflags(+)BARREL_NO_DROP; if(self.health) self.max_health=self.health; spawn_barrel(BARREL_INDESTRUCTIBLE); if(!self.max_health) self.max_health=self.health; self.mass = 95; } /*QUAKED obj_barrel_exploding (0.3 0.1 0.6) (-13 -13 0) (13 13 36) DOWNHILL NO_DROP ON_SIDE SINK DROP_USE RESPAWN An exploding barrel with red XXX on the side WARNING!: Putting too many exploding barrels next to each other will cause a crash, there is no way around this, so if it happens, it's to be considered a Designer error! Putting them in lines and chains seems to be ok, as long as you don't stack them or group them too closely, more than 4 in a tight group is probably pushing it. -------------------------FIELDS------------------------- .health - How hard it is to blow up Default: 25 .targetname - set a targetname on a barrel and it will not delay when it explodes (default is arandom delay to prevent too many explosions at once) DOWNHILL - This barrel will slide downhill with gravity. NO_DROP - Will not drop to floor before spawning ON_SIDE - Will make the barrel appear to be on it's side, the top will point right (90 degrees) Note- barrels on their side must be placed at least 13 units above the floor. SINK - Sinks in water DROP_USE - Barrel has no gravity until used, then will drop RESPAWN - Barrel will RESPAWN at it's initial origin when it is destroyed -------------------------------------------------------- */ void obj_barrel_exploding(void) { if(self.spawnflags&DROP_USE) self.spawnflags(+)BARREL_NO_DROP; if(self.health) self.max_health=self.health; spawn_barrel(BARREL_EXPLODING); if(!self.max_health) self.max_health=self.health; self.mass = 85; } /*QUAKED obj_barrel_gfire (0.3 0.1 0.6) (-13 -13 0) (13 13 36) DOWNHILL NO_DROP ON_SIDE SINK DROP_USE RESPAWN Greek fire barrel Use a torch to light them -------------------------FIELDS------------------------- .health - How hard it is to blow up Default: 25 .targetname - set a targetname on a barrel and it will not delay when it explodes (default is arandom delay to prevent too many explosions at once) DOWNHILL - This barrel will slide downhill with gravity. NO_DROP - Will not drop to floor before spawning ON_SIDE - Will make the barrel appear to be on it's side, the top will point right (90 degrees) Note- barrels on their side must be placed at least 13 units above the floor. SINK - Sinks in water DROP_USE - Barrel has no gravity until used, then will drop RESPAWN - Barrel will RESPAWN at it's initial origin when it is destroyed -------------------------------------------------------- */ void obj_barrel_gfire(void) { precache_model("models/newfire.mdl"); precache_model("models/gfire.mdl"); precache_sound("misc/flamloop.wav"); precache_sound("misc/gflaunch.wav"); if(self.spawnflags&DROP_USE) self.spawnflags(+)BARREL_NO_DROP; if(self.health) self.max_health=self.health; spawn_barrel(BARREL_GFIRE); self.mass = 100; if(!self.max_health) self.max_health=self.health; } void barrel_go(void) { // dprint("Barrel_go: ready to respawn\n"); if(self.classname=="obj_barrel_normal") { // dprint("Respawning normal barrel\n"); if(self.spawnflags&DROP_USE) self.spawnflags(+)BARREL_NO_DROP; spawn_barrel(BARREL_NORMAL); self.mass = 75; } else if(self.classname=="obj_barrel_indestructible") { // dprint("Respawning invincible barrel\n"); if(self.spawnflags&DROP_USE) self.spawnflags(+)BARREL_NO_DROP; spawn_barrel(BARREL_INDESTRUCTIBLE); self.mass = 95; } else if(self.classname=="obj_barrel_exploding") { // dprint("Respawning explode barrel\n"); if(self.spawnflags&DROP_USE) self.spawnflags(+)BARREL_NO_DROP; spawn_barrel(BARREL_EXPLODING); self.mass = 100;//85 } else if(self.classname=="obj_barrel_gfire") { // dprint("Respawning gfire barrel\n"); if(self.spawnflags&DROP_USE) self.spawnflags(+)BARREL_NO_DROP; spawn_barrel(BARREL_GFIRE); self.mass = 100;//85 } else { // dprint("NO BARREL TYPE!!!\n"); if(self.spawnflags&DROP_USE) self.spawnflags(+)BARREL_NO_DROP; spawn_barrel(BARREL_EXPLODING); self.mass = 100;//85 } }