/*QUAKED func_explosive (0 .5 .8) ? Trigger_Spawn ANIMATED ANIMATED_FAST Any brush that you want to explode or break apart. If you want an ex0plosion, set dmg and it will do a radius explosion of that amount at the center of the bursh. If targeted it will not be shootable. health defaults to 100. mass defaults to 75. This determines how much debris is emitted when it explodes. You get one large chunk per 100 of mass (up to 8) and one small chunk per 25 of mass (up to 16). So 800 gives the most. */ void func_explosive_explode(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { vec3_t origin; vec3_t chunkorigin; vec3_t size; int count; int mass; // bmodel origins are (0 0 0), we need to adjust that here VectorScale(self->size, 0.5f, size); VectorAdd(self->absmin, size, origin); VectorCopy(origin, self->s.origin); self->takedamage = DAMAGE_NO; if (self->dmg) T_RadiusDamage(self, attacker, self->dmg, NULL, self->dmg + 40, MOD_EXPLOSIVE); VectorSubtract(self->s.origin, inflictor->s.origin, self->velocity); VectorNormalize(self->velocity); VectorScale(self->velocity, 150, self->velocity); // start chunks towards the center VectorScale(size, 0.5f, size); mass = self->mass; if (!mass) mass = 75; // big chunks if (mass >= 100) { count = mass / 100; if (count > 8) count = 8; while (count--) { chunkorigin[0] = origin[0] + crandom() * size[0]; chunkorigin[1] = origin[1] + crandom() * size[1]; chunkorigin[2] = origin[2] + crandom() * size[2]; ThrowDebris(self, "models/objects/debris1/tris.md2", 1, chunkorigin); } } // small chunks count = mass / 25; if (count > 16) count = 16; while (count--) { chunkorigin[0] = origin[0] + crandom() * size[0]; chunkorigin[1] = origin[1] + crandom() * size[1]; chunkorigin[2] = origin[2] + crandom() * size[2]; ThrowDebris(self, "models/objects/debris2/tris.md2", 2, chunkorigin); } G_UseTargets(self, attacker); if (self->dmg) BecomeExplosion1(self); else G_FreeEdict(self); }
void sandbag_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { vec3_t org; org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris1/tris.md2", 1, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris1/tris.md2", 1, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris1/tris.md2", 1, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris1/tris.md2", 1, org); gi.positioned_sound (self->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("faf/woodbreak.wav"), .7, ATTN_NORM, 0); if (self->obj_owner == 0) allied_sandbags--; else if (self->obj_owner == 1) axis_sandbags--; G_FreeEdict (self); }
/* ================= fire_rocket ================= */ void rocket_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) { vec3_t origin; int n; if (other == ent->owner) return; if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict (ent); return; } if (ent->owner->client) PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); // calculate position for the explosion entity VectorMA (ent->s.origin, -0.02, ent->velocity, origin); fire_grenade3 (ent, ent->s.origin, ent->s.origin, 150, 0, 2.5, 200); if (other->takedamage) { T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, ent->dmg, 0, 0, MOD_ROCKET); } else { // don't throw any debris in net games if (!deathmatch->value && !coop->value) { if ((surf) && !(surf->flags & (SURF_WARP|SURF_TRANS33|SURF_TRANS66|SURF_FLOWING))) { n = rand() % 5; while(n--) ThrowDebris (ent, "models/objects/debris2/tris.md2", 2, ent->s.origin); } } } T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other, ent->dmg_radius, MOD_R_SPLASH); gi.WriteByte (svc_temp_entity); if (ent->waterlevel) gi.WriteByte (TE_ROCKET_EXPLOSION_WATER); else gi.WriteByte (TE_ROCKET_EXPLOSION); gi.WritePosition (origin); gi.multicast (ent->s.origin, MULTICAST_PHS); G_FreeEdict (ent); }
void barrel_explode (edict_t *self) { vec3_t org; float spd; vec3_t save; T_RadiusDamage (self, self->activator, self->dmg, NULL, self->dmg+40, MOD_BARREL); VectorCopy (self->s.origin, save); VectorMA (self->absmin, 0.5, self->size, self->s.origin); // a few big chunks spd = 1.5 * (float)self->dmg / 200.0; org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris1/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris1/tris.md2", spd, org); // bottom corners spd = 1.75 * (float)self->dmg / 200.0; VectorCopy (self->absmin, org); ThrowDebris (self, "models/objects/debris3/tris.md2", spd, org); VectorCopy (self->absmin, org); org[0] += self->size[0]; ThrowDebris (self, "models/objects/debris3/tris.md2", spd, org); VectorCopy (self->absmin, org); org[1] += self->size[1]; ThrowDebris (self, "models/objects/debris3/tris.md2", spd, org); VectorCopy (self->absmin, org); org[0] += self->size[0]; org[1] += self->size[1]; ThrowDebris (self, "models/objects/debris3/tris.md2", spd, org); // a bunch of little chunks spd = 2 * self->dmg / 200; org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org); org[0] = self->s.origin[0] + crandom() * self->size[0]; org[1] = self->s.origin[1] + crandom() * self->size[1]; org[2] = self->s.origin[2] + crandom() * self->size[2]; ThrowDebris (self, "models/objects/debris2/tris.md2", spd, org); VectorCopy (save, self->s.origin); if (self->groundentity) BecomeExplosion2 (self); else BecomeExplosion1 (self); }
void pendulum_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { // Mostly copied from func_explosive_explode. We can't use that function because // the origin is a bit different. vec3_t origin; vec3_t forward, left, up; vec3_t chunkorigin; vec3_t size; int count; int mass; // Particles originate from business end of pendulum AngleVectors(self->s.angles,forward,left,up); VectorScale(forward,self->move_origin[0],forward); VectorScale(left,-self->move_origin[1],left); VectorScale(up,self->move_origin[2],up); VectorAdd(self->s.origin,forward,origin); VectorAdd(origin,left,origin); VectorAdd(origin,up,origin); self->mass *= 2; self->takedamage = DAMAGE_NO; VectorSubtract (origin, self->enemy->s.origin, self->velocity); VectorNormalize (self->velocity); VectorScale (self->velocity, 150, self->velocity); // start chunks towards the center VectorScale (size, 0.5, size); mass = self->mass; if (!mass) mass = 75; // big chunks if (mass >= 100) { count = mass / 100; if (count > 8) count = 8; while(count--) { chunkorigin[0] = origin[0] + crandom() * size[0]; chunkorigin[1] = origin[1] + crandom() * size[1]; chunkorigin[2] = origin[2] + crandom() * size[2]; ThrowDebris (self, "models/objects/debris1/tris.md2", 1, chunkorigin, 0, 0); } } // small chunks count = mass / 25; if (count > 16) count = 16; while(count--) { chunkorigin[0] = origin[0] + crandom() * size[0]; chunkorigin[1] = origin[1] + crandom() * size[1]; chunkorigin[2] = origin[2] + crandom() * size[2]; ThrowDebris (self, "models/objects/debris2/tris.md2", 2, chunkorigin, 0, 0); } G_FreeEdict (self); }
static void func_explosive_explode( edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, const vec3_t point ) { vec3_t origin, bakorigin; vec3_t chunkorigin; vec3_t size; int count; int mass; // do not explode unless visible if( self->r.svflags & SVF_NOCLIENT ) return; self->takedamage = DAMAGE_NO; // bmodel origins are (0 0 0), we need to adjust that here VectorCopy( self->s.origin, bakorigin ); VectorScale( self->r.size, 0.5, size ); VectorAdd( self->r.absmin, size, origin ); VectorCopy( origin, self->s.origin ); if( self->projectileInfo.maxDamage ) G_RadiusDamage( self, attacker, NULL, NULL, MOD_EXPLOSIVE ); VectorSubtract( self->s.origin, inflictor->s.origin, self->velocity ); VectorNormalize( self->velocity ); VectorScale( self->velocity, 150, self->velocity ); // start chunks towards the center VectorScale( size, 0.5, size ); mass = self->projectileInfo.radius * 0.75; if( !mass ) mass = 75; // big chunks if( self->count > 0 ) { if( mass >= 100 ) { count = mass / 100; if( count > 8 ) count = 8; while( count-- ) { chunkorigin[0] = origin[0] + crandom() * size[0]; chunkorigin[1] = origin[1] + crandom() * size[1]; chunkorigin[2] = origin[2] + crandom() * size[2]; ThrowDebris( self, self->count, 1, chunkorigin ); } } } // small chunks if( self->viewheight > 0 ) { count = mass / 25; if( count > 16 ) count = 16; if( count < 1 ) count = 1; while( count-- ) { chunkorigin[0] = origin[0] + crandom() * size[0]; chunkorigin[1] = origin[1] + crandom() * size[1]; chunkorigin[2] = origin[2] + crandom() * size[2]; ThrowDebris( self, self->viewheight, 2, chunkorigin ); } } G_UseTargets( self, attacker ); if( self->projectileInfo.maxDamage ) { edict_t *explosion; explosion = G_Spawn(); VectorCopy( self->s.origin, explosion->s.origin ); explosion->projectileInfo = self->projectileInfo; BecomeExplosion1( explosion ); } if( self->use == NULL ) { G_FreeEdict( self ); return; } self->health = self->max_health; self->r.solid = SOLID_NOT; self->r.svflags |= SVF_NOCLIENT; VectorCopy( bakorigin, self->s.origin ); VectorClear( self->velocity ); GClip_LinkEntity( self ); }
void airstrike_touch_i (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) { vec3_t origin; int n; vec3_t end, world_up, start; trace_t tr; VectorSet(world_up, 0, 0, 1); VectorCopy(ent->s.origin, start); VectorMA(start, 8192, world_up, end); tr = gi.trace(start, NULL, NULL, end, ent, MASK_SHOT|CONTENTS_SLIME|CONTENTS_LAVA); //this happens on invade1. bomb gets dropped inside the pill if ( tr.surface && !(tr.surface->flags & SURF_SKY) ) { ent->think = G_FreeEdict; ent->nextthink = level.time + .1; return; } if (other == ent->owner) return; if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict (ent); return; } // if (ent->owner->client) // PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); // calculate position for the explosion entity VectorMA (ent->s.origin, -0.02, ent->velocity, origin); if (other->takedamage) { T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, ent->dmg, 0, 0, MOD_AIRSTRIKE); } else { // don't throw any debris in net games //if (!deathmatch->value && !coop->value) //{ if ((surf) && !(surf->flags & (SURF_WARP|SURF_TRANS33|SURF_TRANS66|SURF_FLOWING))) { n = rand() % 5; while(n--) ThrowDebris (ent, "models/objects/debris2/tris.md2", 2, ent->s.origin); } //} } T_RadiusDamage(ent, ent, ent->radius_dmg, other, ent->dmg_radius, MOD_AIRSTRIKE_SPLASH); gi.WriteByte (svc_temp_entity); if (ent->waterlevel) gi.WriteByte (TE_ROCKET_EXPLOSION_WATER); else gi.WriteByte (TE_ROCKET_EXPLOSION); gi.WritePosition (origin); gi.multicast (ent->s.origin, MULTICAST_PHS); G_FreeEdict (ent); }
/* ======================== func_explosive_objective ======================== */ void func_explosive_objective_explode (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { vec3_t origin; vec3_t chunkorigin; vec3_t size; int count; int mass; int enemy; int otherteam; //gi.dprintf(DEVELOPER_MSG_GAME, "self: %s\ninflictor: %s\n attacker: %s\n", // self->classname, inflictor->classname, attacker->classname); if (!attacker->client || !attacker->client->resp.mos) return; // bmodel origins are (0 0 0), we need to adjust that here VectorScale (self->size, 0.5, size); VectorAdd (self->absmin, size, origin); VectorCopy (origin, self->s.origin); self->takedamage = DAMAGE_NO; if (self->dmg) T_RadiusDamage (self, attacker, self->dmg, NULL, self->dmg+40, MOD_EXPLOSIVE); VectorSubtract (self->s.origin, inflictor->s.origin, self->velocity); VectorNormalize (self->velocity); VectorScale (self->velocity, 150, self->velocity); // start chunks towards the center VectorScale (size, 0.5, size); mass = self->mass; if (!mass) mass = 75; // big chunks if (mass >= 100) { count = mass / 100; if (count > 8) count = 8; while(count--) { chunkorigin[0] = origin[0] + crandom() * size[0]; chunkorigin[1] = origin[1] + crandom() * size[1]; chunkorigin[2] = origin[2] + crandom() * size[2]; ThrowDebris (self, "models/objects/debris1/tris.md2", 1, chunkorigin); } } // small chunks count = mass / 25; if (count > 16) count = 16; while(count--) { chunkorigin[0] = origin[0] + crandom() * size[0]; chunkorigin[1] = origin[1] + crandom() * size[1]; chunkorigin[2] = origin[2] + crandom() * size[2]; ThrowDebris (self, "models/objects/debris2/tris.md2", 2, chunkorigin); } G_UseTargets (self, attacker); // hack for 2 team games if (self->obj_owner != 99) { team_list[self->obj_owner]->score -= self->obj_loss; enemy = (self->obj_owner) ? 0 : 1; } else enemy = 99; if (self->obj_owner != attacker->client->resp.team_on->index) team_list[attacker->client->resp.team_on->index]->score += self->obj_gain; else if (self->obj_owner == attacker->client->resp.team_on->index && enemy != 99) team_list[enemy]->score += self->obj_gain; if (dedicated->value) safe_cprintf(NULL, PRINT_HIGH, "%s destroyed by %s [%s]\n", self->obj_name, attacker->client->pers.netname, team_list[attacker->client->resp.team_on->index]->teamname); centerprintall("%s destroyed by:\n\n%s\n%s", self->obj_name, attacker->client->pers.netname, team_list[attacker->client->resp.team_on->index]->teamname); otherteam = (self->obj_owner+1)%2; if ((!team_list[otherteam]->kills_and_points && team_list[otherteam]->score < team_list[otherteam]->need_points) || (team_list[otherteam]->kills_and_points && team_list[otherteam]->kills < team_list[otherteam]->need_kills)) gi.sound(self, CHAN_NO_PHS_ADD, gi.soundindex(va("%s/objectives/touch_cap.wav", team_list[otherteam]->teamid)), 1, 0, 0); // gi.dprintf(DEVELOPER_MSG_GAME, "pts:%i ndpts:%i kills:%i ndkills:%i\n",team_list[(self->obj_owner+1)%2]->score,team_list[(self->obj_owner+1)%2]->need_points, //team_list[(self->obj_owner+1)%2]->kills,team_list[(self->obj_owner+1)%2]->need_kills); if (self->deathtarget) { self->target = self->deathtarget; if (self->target) G_UseTargets (self, attacker); } if (self->dmg) BecomeExplosion1 (self); else G_FreeEdict (self); }
/*QUAKED func_explosive (0 .5 .8) ? Trigger_Spawn ANIMATED ANIMATED_FAST INACTIVE Any brush that you want to explode or break apart. If you want an ex0plosion, set dmg and it will do a radius explosion of that amount at the center of the bursh. If targeted it will not be shootable. INACTIVE - specifies that the entity is not explodable until triggered. If you use this you must target the entity you want to trigger it. This is the only entity approved to activate it. health defaults to 100. mass defaults to 75. This determines how much debris is emitted when it explodes. You get one large chunk per 100 of mass (up to 8) and one small chunk per 25 of mass (up to 16). So 800 gives the most. */ void func_explosive_explode (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { vec3_t origin; vec3_t chunkorigin; vec3_t size; int count; int mass; edict_t *master; qboolean done = false; // bmodel origins are (0 0 0), we need to adjust that here VectorScale (self->size, 0.5, size); VectorAdd (self->absmin, size, origin); VectorCopy (origin, self->s.origin); self->takedamage = DAMAGE_NO; if (self->dmg) T_RadiusDamage (self, attacker, self->dmg, NULL, self->dmg+40, MOD_EXPLOSIVE); VectorSubtract (self->s.origin, inflictor->s.origin, self->velocity); VectorNormalize (self->velocity); VectorScale (self->velocity, 150, self->velocity); // start chunks towards the center VectorScale (size, 0.5, size); mass = self->mass; if (!mass) mass = 75; // big chunks if (mass >= 100) { count = mass / 100; if (count > 8) count = 8; while(count--) { chunkorigin[0] = origin[0] + crandom() * size[0]; chunkorigin[1] = origin[1] + crandom() * size[1]; chunkorigin[2] = origin[2] + crandom() * size[2]; ThrowDebris (self, "models/objects/debris1/tris.md2", 1, chunkorigin); } } // small chunks count = mass / 25; if (count > 16) count = 16; while(count--) { chunkorigin[0] = origin[0] + crandom() * size[0]; chunkorigin[1] = origin[1] + crandom() * size[1]; chunkorigin[2] = origin[2] + crandom() * size[2]; ThrowDebris (self, "models/objects/debris2/tris.md2", 2, chunkorigin); } // PMM - if we're part of a train, clean ourselves out of it if (self->flags & FL_TEAMSLAVE) { if (self->teammaster) { master = self->teammaster; if(master && master->inuse) // because mappers (other than jim (usually)) are stupid.... { while (!done) { if (master->teamchain == self) { master->teamchain = self->teamchain; done = true; } master = master->teamchain; } } } } G_UseTargets (self, attacker); if (self->dmg) BecomeExplosion1 (self); else G_FreeEdict (self); }