/* * QUAKED target_changelevel (1 0 0) (-8 -8 -8) (8 8 8) * Changes level to "map" when fired */ void use_target_changelevel(edict_t *self, edict_t *other, edict_t *activator) { if (!self || !other || !activator) { return; } if (level.intermissiontime) { return; /* already activated */ } if (!deathmatch->value && !coop->value) { if (g_edicts[1].health <= 0) { return; } } /* if noexit, do a ton of damage to other */ if (deathmatch->value && !((int)dmflags->value & DF_ALLOW_EXIT) && (other != world)) { T_Damage(other, self, self, vec3_origin, other->s.origin, vec3_origin, 10 * other->max_health, 1000, 0, MOD_EXIT); return; } /* if multiplayer, let everyone know who hit the exit */ if (deathmatch->value) { if (activator && activator->client) { gi.bprintf(PRINT_HIGH, "%s exited the level.\n", activator->client->pers.netname); } } /* if going to a new unit, clear cross triggers */ if (strstr(self->map, "*")) { game.serverflags &= ~(SFL_CROSS_TRIGGER_MASK); } BeginIntermission(self); }
void parasite_drain_attack (edict_t *self) { vec3_t offset, start, f, r, end, dir; trace_t tr; int damage; AngleVectors (self->s.angles, f, r, NULL); VectorSet (offset, 24, 0, 6); G_ProjectSource (self->s.origin, offset, f, r, start); VectorCopy (self->enemy->s.origin, end); if (!parasite_drain_attack_ok(start, end)) { end[2] = self->enemy->s.origin[2] + self->enemy->maxs[2] - 8; if (!parasite_drain_attack_ok(start, end)) { end[2] = self->enemy->s.origin[2] + self->enemy->mins[2] + 8; if (!parasite_drain_attack_ok(start, end)) return; } } VectorCopy (self->enemy->s.origin, end); tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT); if (tr.ent != self->enemy) return; if (self->s.frame == FRAME_drain03) { damage = 5; gi.sound (self->enemy, CHAN_AUTO, sound_impact, 1, ATTN_NORM, 0); } else { if (self->s.frame == FRAME_drain04) gi.sound (self, CHAN_WEAPON, sound_suck, 1, ATTN_NORM, 0); damage = 2; } gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_PARASITE_ATTACK); gi.WriteShort (self - g_edicts); gi.WritePosition (start); gi.WritePosition (end); gi.multicast (self->s.origin, MULTICAST_PVS); VectorSubtract (start, end, dir); T_Damage (self->enemy, self, self, dir, self->enemy->s.origin, vec3_origin, damage, 0, DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN); }
void forcewall_knockback (edict_t *self, edict_t *other) { int dmg; vec3_t forward, zvec={0,0,0}; trace_t tr; dmg = 20*self->activator->myskills.abilities[FORCE_WALL].current_level; tr = gi.trace (other->s.origin, NULL, NULL, self->s.origin, other, MASK_SHOT); T_Damage (other, self, self->activator, zvec, other->s.origin, NULL, dmg, 1, DAMAGE_ENERGY, MOD_BURN); vectoangles(tr.plane.normal, forward); AngleVectors(forward, forward, NULL, NULL); other->velocity[0] = forward[0]*250; other->velocity[1] = forward[1]*250; other->velocity[2] = 200; }
void turret_blocked (edict_t * self, edict_t * other) { edict_t *attacker; if (other->takedamage) { if (self->teammaster->owner) attacker = self->teammaster->owner; else attacker = self->teammaster; T_Damage (other, self, attacker, vec3_origin, other->s.origin, vec3_origin, self->teammaster->dmg, 10, 0, MOD_CRUSH); } }
void door_blocked() { other->deathtype = "squish"; T_Damage( other, self, PROG_TO_EDICT( self->s.v.goalentity ), self->dmg ); // if a door has a negative wait, it would never come back if blocked, // so let it just squash the object to death real fast if ( self->wait >= 0 ) { if ( self->state == STATE_DOWN ) door_go_up(); else door_go_down(); } }
void door_blocked (edict_t *self, edict_t *other) { edict_t *ent; if (!(other->svflags & SVF_MONSTER) && (!other->client) ) { // give it a chance to go away on it's own terms (like gibs) T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 100000, 1, 0, MOD_CRUSH); // if it's still there, nuke it if (other) BecomeExplosion1 (other); return; } T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, 1, 0, MOD_CRUSH); if (self->spawnflags & DOOR_CRUSHER) return; // if a door has a negative wait, it would never come back if blocked, // so let it just squash the object to death real fast if (self->moveinfo.wait >= 0) { if (self->moveinfo.state == STATE_DOWN) { for (ent = self->teammaster ; ent ; ent = ent->teamchain) door_go_up (ent, ent->activator); } else { for (ent = self->teammaster ; ent ; ent = ent->teamchain) door_go_down (ent); } } }
void T_RadiusDamage(edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod) { float points; edict_t *ent = NULL; vec3_t v; vec3_t dir; if (!inflictor || !attacker) { return; } while ((ent = findradius(ent, inflictor->s.origin, radius)) != NULL) { if (ent == ignore) { continue; } if (!ent->takedamage) { continue; } VectorAdd(ent->mins, ent->maxs, v); VectorMA(ent->s.origin, 0.5, v, v); VectorSubtract(inflictor->s.origin, v, v); points = damage - 0.5 * VectorLength(v); if (ent == attacker) { points = points * 0.5; } if (points > 0) { if (CanDamage(ent, inflictor)) { VectorSubtract(ent->s.origin, inflictor->s.origin, dir); T_Damage(ent, inflictor, attacker, dir, inflictor->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod); } } } }
/* ============ T_RadiusDamage ============ */ void T_RadiusDamage (edict_t * inflictor, edict_t * attacker, float damage, edict_t * ignore, float radius, int mod) { float points; edict_t *ent = NULL; vec3_t v; vec3_t dir; while ((ent = findradius (ent, inflictor->s.origin, radius)) != NULL) { if (ent == ignore) continue; if (!ent->takedamage) continue; VectorAdd (ent->mins, ent->maxs, v); VectorMA (ent->s.origin, 0.5, v, v); VectorSubtract (inflictor->s.origin, v, v); points = damage - 0.5 * VectorLength (v); //zucc reduce damage for crouching, max is 32 when standing if (ent->maxs[2] < 20) { points = points * 0.5; // hefty reduction in damage } //if (ent == attacker) //points = points * 0.5; if (points > 0) { #ifdef _DEBUG if (0 == Q_stricmp (ent->classname, "func_explosive")) { CGF_SFX_ShootBreakableGlass (ent, inflictor, 0, mod); } else #endif if (CanDamage (ent, inflictor)) { VectorSubtract (ent->s.origin, inflictor->s.origin, dir); // zucc scaled up knockback(kick) of grenades T_Damage (ent, inflictor, attacker, dir, ent->s.origin, vec3_origin, (int) (points * .75), (int) (points * .75), DAMAGE_RADIUS, mod); } } } }
/* ============= ai_melee ============= */ void ai_melee() { vec3_t delta; float ldmg; if ( !self->s.v.enemy ) return; // removed before stroke VectorSubtract( PROG_TO_EDICT( self->s.v.enemy )->s.v.origin, self->s.v.origin, delta ); if ( vlen( delta ) > 60 ) return; ldmg = ( g_random() + g_random() + g_random() ) * 3; PROG_TO_EDICT( self->s.v.enemy )->deathtype = dtSQUISH; // FIXME T_Damage( PROG_TO_EDICT( self->s.v.enemy ), self, self, ldmg ); }
void CTFGrappleTouch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { float volume = 1.0; if (other == self->owner) return; if (self->owner->client->ctf_grapplestate != CTF_GRAPPLE_STATE_FLY) return; if (surf && (surf->flags & SURF_SKY)) { CTFResetGrapple(self); return; } VectorCopy(vec3_origin, self->velocity); PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); if (other->takedamage) { T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, 0, MOD_GRAPPLE); CTFResetGrapple(self); return; } self->owner->client->ctf_grapplestate = CTF_GRAPPLE_STATE_PULL; // we're on hook self->enemy = other; self->solid = SOLID_NOT; if (self->owner->client->silencer_shots) volume = 0.2; gi.sound (self->owner, CHAN_RELIABLE+CHAN_WEAPON, gi.soundindex("weapons/grapple/grpull.wav"), volume, ATTN_NORM, 0); gi.sound (self, CHAN_WEAPON, gi.soundindex("weapons/grapple/grhit.wav"), volume, ATTN_NORM, 0); gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_SPARKS); gi.WritePosition (self->s.origin); if (!plane) gi.WriteDir (vec3_origin); else gi.WriteDir (plane->normal); gi.multicast (self->s.origin, MULTICAST_PVS); }
void abortHeal (edict_t *self, qboolean change_frame, qboolean gib, qboolean mark) { int hurt; static vec3_t pain_normal = { 0, 0, 1 }; // clean up target cleanupHeal (self, change_frame); // gib em! if ((mark) && (self->enemy) && (self->enemy->inuse)) { // if ((g_showlogic) && (g_showlogic->value)) // gi.dprintf ("%s - marking target as bad\n", self->classname); // if the first badMedic slot is filled by a medic, skip it and use the second one if ((self->enemy->monsterinfo.badMedic1) && (self->enemy->monsterinfo.badMedic1->inuse) && (!strncmp(self->enemy->monsterinfo.badMedic1->classname, "monster_medic", 13)) ) { self->enemy->monsterinfo.badMedic2 = self; } else { self->enemy->monsterinfo.badMedic1 = self; } } if ((gib) && (self->enemy) && (self->enemy->inuse)) { // if ((g_showlogic) && (g_showlogic->value)) // gi.dprintf ("%s - gibbing bad heal target", self->classname); if(self->enemy->gib_health) hurt = - self->enemy->gib_health; else hurt = 500; T_Damage (self->enemy, self, self, vec3_origin, self->enemy->s.origin, pain_normal, hurt, 0, 0, MOD_UNKNOWN); } // clean up self self->monsterinfo.aiflags &= ~AI_MEDIC; if ((self->oldenemy) && (self->oldenemy->inuse)) self->enemy = self->oldenemy; else self->enemy = NULL; self->monsterinfo.medicTries = 0; }
void plasma_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) { vec3_t origin; if (!ent || !other || !plane || !surf) { 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_PHALANX); } T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other, ent->dmg_radius, MOD_PHALANX); gi.WriteByte(svc_temp_entity); gi.WriteByte(TE_PLASMA_EXPLOSION); gi.WritePosition(origin); gi.multicast(ent->s.origin, MULTICAST_PVS); G_FreeEdict(ent); }
void mutant_jump_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurface_t *surf /* unused */) { if (!self || !other) { return; } if (self->health <= 0) { self->touch = NULL; return; } if (other->takedamage) { if (VectorLength(self->velocity) > 400) { vec3_t point; vec3_t normal; int damage; VectorCopy(self->velocity, normal); VectorNormalize(normal); VectorMA(self->s.origin, self->maxs[0], normal, point); damage = 40 + 10 * random(); T_Damage(other, self, self, self->velocity, point, normal, damage, damage, 0, MOD_UNKNOWN); } } if (!M_CheckBottom(self)) { if (self->groundentity) { self->monsterinfo.nextframe = FRAME_attack02; self->touch = NULL; } return; } self->touch = NULL; }
void flyer_kamikaze_explode (edict_t *self) { vec3_t dir; if (self->monsterinfo.commander && self->monsterinfo.commander->inuse && !strcmp(self->monsterinfo.commander->classname, "monster_carrier")) { self->monsterinfo.commander->monsterinfo.monster_slots++; } if (self->enemy) { VectorSubtract (self->enemy->s.origin, self->s.origin, dir); T_Damage (self->enemy, self, self, dir, self->s.origin, vec3_origin, (int)50, (int)50, DAMAGE_RADIUS, MOD_UNKNOWN); } flyer_die (self, NULL, NULL, 0, dir); }
void KillChildren (edict_t *self) { edict_t *ent; int field; ent = NULL; field = FOFS(classname); while (1) { ent = G_Find (ent, field, "monster_stalker"); if(!ent) return; // FIXME - may need to stagger if ((ent->inuse) && (ent->health > 0)) T_Damage (ent, self, self, vec3_origin, self->enemy->s.origin, vec3_origin, (ent->health + 1), 0, DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN); } }
/* ================= fire_bfg ================= */ void bfg_explode (edict_t *self) { edict_t *ent; float points; vec3_t v; float dist; if (self->s.frame == 0) { // the BFG effect ent = NULL; while ((ent = findradius(ent, self->s.origin, self->dmg_radius)) != NULL) { if (!ent->takedamage) continue; if (ent == self->owner) continue; if (!CanDamage (ent, self)) continue; if (!CanDamage (ent, self->owner)) continue; VectorAdd (ent->mins, ent->maxs, v); VectorMA (ent->s.origin, 0.5, v, v); VectorSubtract (self->s.origin, v, v); dist = VectorLength(v); points = self->radius_dmg * (1.0 - sqrt(dist/self->dmg_radius)); // PMM - happened to notice this copy/paste bug // if (ent == self->owner) // points = points * 0.5; gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BFG_EXPLOSION); gi.WritePosition (ent->s.origin); gi.multicast (ent->s.origin, MULTICAST_PHS); T_Damage (ent, self, self->owner, self->velocity, ent->s.origin, vec3_origin, (int)points, 0, DAMAGE_ENERGY, MOD_BFG_EFFECT); } } self->nextthink = level.time + FRAMETIME; self->s.frame++; if (self->s.frame == 5) self->think = G_FreeEdict; }
void spike_touch() { //float rand; if ( other == PROG_TO_EDICT( self->s.v.owner ) ) return; if ( self->voided ) { return; } self->voided = 1; if ( other->s.v.solid == SOLID_TRIGGER ) return; // trigger field, do nothing if ( trap_pointcontents( PASSVEC3( self->s.v.origin ) ) == CONTENT_SKY ) { ent_remove( self ); return; } // hit something that bleeds if ( other->s.v.takedamage ) { spawn_touchblood( 9 ); other->deathtype = "nail"; T_Damage( other, self, PROG_TO_EDICT( self->s.v.owner ), 9 ); } else { trap_WriteByte( MSG_MULTICAST, SVC_TEMPENTITY ); if ( !strcmp( self->s.v.classname, "wizspike" ) ) trap_WriteByte( MSG_MULTICAST, TE_WIZSPIKE ); else if ( !strcmp( self->s.v.classname, "knightspike" ) ) trap_WriteByte( MSG_MULTICAST, TE_KNIGHTSPIKE ); else trap_WriteByte( MSG_MULTICAST, TE_SPIKE ); trap_WriteCoord( MSG_MULTICAST, self->s.v.origin[0] ); trap_WriteCoord( MSG_MULTICAST, self->s.v.origin[1] ); trap_WriteCoord( MSG_MULTICAST, self->s.v.origin[2] ); trap_multicast( PASSVEC3( self->s.v.origin ), MULTICAST_PHS ); } ent_remove( 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); 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); }
// // GrappleTrack - Constantly updates the hook's position relative to // what it's hooked to. Inflicts damage if attached to // a player that is not on the same team as the hook's // owner. // void GrappleTrack() { gedict_t *enemy = PROG_TO_EDICT(self->s.v.enemy); gedict_t *owner = PROG_TO_EDICT(self->s.v.owner); // Release dead targets if ( enemy->ct == ctPlayer && ISDEAD( enemy ) ) owner->on_hook = false; // drop the hook if owner is dead or has released the button if ( !owner->on_hook || owner->s.v.health <= 0 ) { GrappleReset( self ); return; } if ( enemy->ct == ctPlayer ) { if ( !CanDamage(enemy, owner) ) { GrappleReset( self ); return; } // move the hook along with the player. It's invisible, but // we need this to make the sound come from the right spot setorigin( self, PASSVEC3(enemy->s.v.origin) ); sound ( self, CHAN_WEAPON, "blob/land1.wav", 1, ATTN_NORM ); enemy->deathtype = dtHOOK; T_Damage ( enemy, self, owner, 1 ); trap_makevectors ( self->s.v.v_angle ); SpawnBlood( enemy->s.v.origin, 1 ); } // If the hook is not attached to the player, constantly copy // the target's velocity. Velocity copying DOES NOT work properly // for a hooked client. if ( enemy->ct != ctPlayer ) VectorCopy( enemy->s.v.velocity, self->s.v.velocity ); self->s.v.nextthink = g_globalvars.time + 0.1; }
/* ================= KillBox Kills all entities that would touch the proposed new positioning of ent. Ent should be unlinked before calling this! ================= */ qboolean KillBox (edict_t *ent) { trace_t tr; while (1) { tr = gi.trace (ent->s.origin, ent->mins, ent->maxs, ent->s.origin, NULL, MASK_PLAYERSOLID); if (!tr.ent) break; // nail it T_Damage (tr.ent, ent, ent, vec3_origin, ent->s.origin, vec3_origin, 100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG); // if we didn't kill it, fail if (tr.ent->solid) return false; } return true; // all clear }
void WaterTotem_think(edict_t *self, edict_t *caster) { edict_t *target = NULL; //Find players in radius and attack them. while ((target = findclosestradius(target, self->s.origin, TOTEM_MAX_RANGE)) != NULL) { // (apple) // Since ice talent and watertotem work concurrently now, // checking for chill_duration will throttle ice talent's refire. if (G_ValidTarget(self, target, true)) { vec3_t normal; int talentLevel; float duration = WATERTOTEM_DURATION_BASE + self->monsterinfo.level * WATERTOTEM_DURATION_MULT; //Get a directional vector from the totem to the target. VectorSubtract(self->s.origin, target->s.origin, normal); //Talent: Ice. Damages players. talentLevel = getTalentLevel(caster, TALENT_ICE); if(talentLevel > 0) { int damage = GetRandom(10, 20) * talentLevel; vec3_t normal; //Damage the target VectorSubtract(target->s.origin, self->s.origin, normal); T_Damage(target, self, self, vec3_origin, self->s.origin, normal, damage, 0, DAMAGE_NO_KNOCKBACK, MOD_WATERTOTEM); } //Chill the target. target->chill_level = self->monsterinfo.level; target->chill_time = level.time + duration; //gi.dprintf("chilled %s for %.1f seconds at level %d\n", target->classname, duration, self->monsterinfo.level); } } //Next think. self->delay = level.time + WATERTOTEM_REFIRE_BASE + WATERTOTEM_REFIRE_MULT * self->monsterinfo.level; }
/* ================= fire_blaster Fires a single blaster bolt. Used by the blaster and hyper blaster. ================= */ void blaster_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { int mod; if (other == self->owner) return; if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict (self); return; } if (self->owner->client) PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); if (other->takedamage) { if (self->spawnflags & 1) mod = MOD_HYPERBLASTER; else mod = MOD_BLASTER; T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, mod); } else { gi.WriteByte (svc_temp_entity); // RAFAEL //if (self->s.effects & TE_BLUEHYPERBLASTER) // gi.WriteByte (TE_BLUEHYPERBLASTER); //else gi.WriteByte (TE_BLASTER); gi.WritePosition (self->s.origin); if (!plane) gi.WriteDir (vec3_origin); else gi.WriteDir (plane->normal); gi.multicast (self->s.origin, MULTICAST_PVS); } G_FreeEdict (self); }
void use_target_changelevel (edict_t *self, edict_t *other, edict_t *activator) { if (level.intermissiontime) return; // already activated // if noexit, do a ton of damage to other if (deathmatch_value && !( (int)dmflags->value & DF_ALLOW_EXIT) && other != world) { T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 10 * other->max_health, 1000, 0, MOD_EXIT); return; } // if multiplayer, let everyone know who hit the exit if (deathmatch_value) { if (activator && activator->client) gi.bprintf (PRINT_HIGH, "%s exited the level.\n", activator->client->pers.netname); } // if going to a new unit, clear cross triggers if (strstr(self->map, "*")) game.serverflags &= ~(SFL_CROSS_TRIGGER_MASK); // Ridah, copy the episode_flags over if (activator->client) { activator->client->pers.episode_flags |= activator->episode_flags; } else // something has gone very wrong { { edict_t *player; player = &g_edicts[1]; activator = player; activator->client->pers.episode_flags |= activator->episode_flags; } } BeginIntermission (self); }
void loogie_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { if (other == self->owner) return; if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict (self); return; } if (self->owner->client) PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); if (other->takedamage) T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, MOD_GEKK); G_FreeEdict (self); };
void Laser_Touch() { vec3_t org; if ( other == PROG_TO_EDICT( self->s.v.owner ) ) return; // don't explode on owner if ( trap_pointcontents( PASSVEC3( self->s.v.origin ) ) == CONTENT_SKY ) { ent_remove( self ); return; } sound( self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_STATIC ); normalize( self->s.v.velocity, org ); VectorScale( org, 8, org ); VectorSubtract( self->s.v.origin, org, org ); //org = self->s.v.origin - 8*normalize(self->s.v.velocity); if ( ISLIVE( other ) ) { SpawnBlood( org, 15 ); other->deathtype = dtLASER; T_Damage( other, self, PROG_TO_EDICT( self->s.v.owner ), 15 ); } else { WriteByte( MSG_MULTICAST, SVC_TEMPENTITY ); WriteByte( MSG_MULTICAST, TE_GUNSHOT ); WriteByte( MSG_MULTICAST, 5 ); WriteCoord( MSG_MULTICAST, org[0] ); WriteCoord( MSG_MULTICAST, org[1] ); WriteCoord( MSG_MULTICAST, org[2] ); trap_multicast( PASSVEC3( org ), MULTICAST_PVS ); } ent_remove( self ); }
void HookTouch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) { if (other == ent->owner) return; if (other->takedamage) { gi.sound (ent, CHAN_WEAPON, sound_hookimpact, 1, ATTN_NORM, 0); T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, 10, 0, 0, MOD_ROCKET); } if(other->client && other->health > 0) { // alive... Let's drag the bastard back... ent->enemy = other; } ent->powerarmor_time = level.time + 15; VectorClear(ent->velocity); ent->nextthink = level.time + FRAMETIME; ent->think = HookDragThink; ent->s.frame = 283; }
/*QUAKED target_changelevel (1 0 0) (-8 -8 -8) (8 8 8) Changes level to "map" when fired */ void use_target_changelevel (edict_t *self, edict_t *other, edict_t *activator) { if (level.intermissionframe) return; // already activated // if noexit, do a ton of damage to other if (!( (int)dmflags->value & DF_ALLOW_EXIT) && other != world) { T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, 10 * other->max_health, 1000, 0, MOD_EXIT); return; } // if multiplayer, let everyone know who hit the exit if (activator && activator->client) gi.bprintf (PRINT_HIGH, "%s exited the level.\n", activator->client->pers.netname); // if going to a new unit, clear cross triggers if (strchr(self->map, '*')) game.serverflags &= ~(SFL_CROSS_TRIGGER_MASK); BeginIntermission (self); }
// ================= // ================= void sphere_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf, int mod) { if(self->spawnflags & SPHERE_DOPPLEGANGER) { if (other == self->teammaster) return; self->takedamage = DAMAGE_NO; self->owner = self->teammaster; self->teammaster = NULL; } else { if (other == self->owner) return; // PMM - don't blow up on bodies if (!strcmp(other->classname, "bodyque")) return; } if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict (self); return; } if (other->takedamage) { T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, 10000, 1, DAMAGE_DESTROY_ARMOR, mod); } else { T_RadiusDamage (self, self->owner, 512, self->owner, 256, mod); } sphere_think_explode (self); }
/* ================= fire_fireball ================= */ void fireball_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { if (other == self->owner) return; if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict (self); return; } if (self->owner->client) PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); if (other->takedamage) { T_Damage(other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, MOD_BOW); gi.sound(other, CHAN_AUTO, gi.soundindex("morrowind/FireballHit.wav"), 1, ATTN_NORM, 0); if (other->client) { other->client->pers.burning = 5; other->client->pers.burner = self->owner; } } else { gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BLASTER); gi.WritePosition (self->s.origin); if (!plane) gi.WriteDir (vec3_origin); else gi.WriteDir (plane->normal); gi.multicast (self->s.origin, MULTICAST_PVS); } G_FreeEdict (self); }
void boss_punch (edict_t *self) { int damage; trace_t tr; edict_t *other=NULL; vec3_t v; if (!self->groundentity) return; damage = TANK_PUNCH_INITIAL_DAMAGE+TANK_PUNCH_ADDON_DAMAGE*self->monsterinfo.level; // T_RadiusDamage(self, self, damage, self, TANK_PUNCH_RADIUS, 0); gi.sound (self, CHAN_AUTO, gi.soundindex ("tank/tnkatck5.wav"), 1, ATTN_NORM, 0); while ((other = findradius(other, self->s.origin, 256)) != NULL) { if (other == self) continue; if (!other->inuse) continue; if (!other->takedamage) continue; if (other->solid == SOLID_NOT) continue; if (!other->groundentity) continue; if (OnSameTeam(self, other)) continue; if (!visible(self, other)) continue; VectorSubtract(other->s.origin, self->s.origin, v); VectorNormalize(v); tr = gi.trace(self->s.origin, NULL, NULL, other->s.origin, self, (MASK_PLAYERSOLID | MASK_MONSTERSOLID)); T_Damage (other, self, self, v, other->s.origin, tr.plane.normal, damage, damage, 0, MOD_TANK_PUNCH); other->velocity[2] += damage / 2; } }