/* ================== player_die ================== */ void player_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { int n; VectorClear (self->avelocity); self->takedamage = DAMAGE_YES; self->movetype = MOVETYPE_TOSS; self->s.modelindex2 = 0; // remove linked weapon model self->s.angles[0] = 0; self->s.angles[2] = 0; self->s.sound = 0; self->client->weapon_sound = 0; self->maxs[2] = -8; // self->solid = SOLID_NOT; self->svflags |= SVF_DEADMONSTER; if (!self->deadflag) { self->client->respawn_time = level.time + 1.0; LookAtKiller (self, inflictor, attacker); self->client->ps.pmove.pm_type = PM_DEAD; ClientObituary (self, inflictor, attacker); TossClientWeapon (self); if (deathmatch->value) Cmd_Help_f (self); // show scores // clear inventory // this is kind of ugly, but it's how we want to handle keys in coop for (n = 0; n < game.num_items; n++) { if (coop->value && itemlist[n].flags & IT_KEY) self->client->resp.coop_respawn.inventory[n] = self->client->pers.inventory[n]; self->client->pers.inventory[n] = 0; } } // remove powerups self->client->quad_framenum = 0; self->client->invincible_framenum = 0; self->client->breather_framenum = 0; self->client->enviro_framenum = 0; self->flags &= ~FL_POWER_ARMOR; if (self->health < -40) { // gib gi.sound (self, CHAN_BODY, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n= 0; n < 4; n++) ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); ThrowClientHead (self, damage); self->takedamage = DAMAGE_NO; } else { // normal death if (!self->deadflag) { static int i; i = (i+1)%3; // start a death animation self->client->anim_priority = ANIM_DEATH; if (self->client->ps.pmove.pm_flags & PMF_DUCKED) { self->s.frame = FRAME_crdeath1-1; self->client->anim_end = FRAME_crdeath5; } else switch (i) { case 0: self->s.frame = FRAME_death101-1; self->client->anim_end = FRAME_death106; break; case 1: self->s.frame = FRAME_death201-1; self->client->anim_end = FRAME_death206; break; case 2: self->s.frame = FRAME_death301-1; self->client->anim_end = FRAME_death308; break; } gi.sound (self, CHAN_VOICE, gi.soundindex(va("*death%i.wav", (rand()%4)+1)), 1, ATTN_NORM, 0); } } self->deadflag = DEAD_DEAD; gi.linkentity (self); }
void soldier_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { int n; self->s.skinnum |= 1; self->monsterinfo.power_armor_type = POWER_ARMOR_NONE; // check for gib if ((self->health <= self->gib_health) && !(self->spawnflags & SF_MONSTER_NOGIB)) { gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 3; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowGib(self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC); ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } // regular death self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->s.skinnum |= 1; if ((self->s.skinnum % 6) == 1) { gi.sound(self, CHAN_VOICE, sound_death_light, 1, ATTN_NORM, 0); } else if ((self->s.skinnum % 6) == 3) { gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); } else // (self->s.skinnum == 5) { gi.sound(self, CHAN_VOICE, sound_death_ss, 1, ATTN_NORM, 0); } if (fabs((self->s.origin[2] + self->viewheight) - point[2]) <= 4) { // head shot self->monsterinfo.currentmove = &soldier_move_death3; return; } n = rand() % 5; if (n == 0) { self->monsterinfo.currentmove = &soldier_move_death1; } else if (n == 1) { self->monsterinfo.currentmove = &soldier_move_death2; } else if (n == 2) { self->monsterinfo.currentmove = &soldier_move_death4; } else if (n == 3) { self->monsterinfo.currentmove = &soldier_move_death5; } else { self->monsterinfo.currentmove = &soldier_move_death6; } }
void T_Damage (edict_t * targ, edict_t * inflictor, edict_t * attacker, vec3_t dir, vec3_t point, vec3_t normal, int damage, int knockback, int dflags, int mod) { gclient_t *client; char buf[256]; int take, save; int asave, psave; int te_sparks, do_sparks = 0; int damage_type = 0; // used for MOD later int bleeding = 0; // damage causes bleeding int head_success = 0; int instant_dam = 1; float z_rel; int height; float from_top; vec_t dist; float targ_maxs2; //FB 6/1/99 // do this before teamplay check if (!targ->takedamage) return; //FIREBLADE if (teamplay->value && mod != MOD_TELEFRAG) { if (lights_camera_action) return; // AQ2:TNG - JBravo adding UVtime if (ctf->value && targ->client) { if(targ->client->ctf_uvtime > 0) return; if (attacker->client && attacker->client->ctf_uvtime > 0) return; } // AQ2:TNG - JBravo adding FF after rounds if (targ != attacker && targ->client && attacker->client && targ->client->resp.team == attacker->client->resp.team && ((int)(dmflags->value) & (DF_NO_FRIENDLY_FIRE))) { if (team_round_going) return; else if (!ff_afterround->value) return; } // AQ:TNG } //FIREBLADE if (dm_shield->value && targ->client) { if (targ->client->ctf_uvtime > 0) return; if (attacker->client && attacker->client->ctf_uvtime > 0) return; } // damage reduction for shotgun // if far away, reduce it to original action levels if (mod == MOD_M3) { dist = Distance(targ->s.origin, inflictor->s.origin); if (dist > 450.0) damage = damage - 2; } targ_maxs2 = targ->maxs[2]; if (targ_maxs2 == 4) targ_maxs2 = CROUCHING_MAXS2; //FB 6/1/99 height = abs (targ->mins[2]) + targ_maxs2; // locational damage code // base damage is head shot damage, so all the scaling is downwards if (targ->client) { if (!((targ != attacker) && ((deathmatch->value && ((int)dmflags->value & (DF_MODELTEAMS | DF_SKINTEAMS))) || coop->value) && (attacker && attacker->client && OnSameTeam (targ, attacker) && ((int)dmflags->value & DF_NO_FRIENDLY_FIRE) && (team_round_going && ff_afterround->value)))) { // TNG Stats - Add +1 to hit, make sure that hc and m3 are handles differently if ((attacker->client) && (mod != MOD_M3) && (mod != MOD_HC)) { strcpy(attacker->client->resp.last_damaged_players, targ->client->pers.netname); if (!teamplay->value || team_round_going || stats_afterround->value) { attacker->client->resp.stats_hits[mod]++; attacker->client->resp.stats_shots_h++; } } // TNG Stats END if (mod == MOD_MK23 || mod == MOD_MP5 || mod == MOD_M4 || mod == MOD_SNIPER || mod == MOD_DUAL || mod == MOD_KNIFE || mod == MOD_KNIFE_THROWN) { z_rel = point[2] - targ->s.origin[2]; from_top = targ_maxs2 - z_rel; if (from_top < 0.0) //FB 6/1/99 from_top = 0.0; //Slightly negative values were being handled wrong bleeding = 1; instant_dam = 0; // damage reduction for longer range pistol shots if (mod == MOD_MK23 || mod == MOD_DUAL) { dist = Distance(targ->s.origin, inflictor->s.origin); if (dist > 600.0 && dist < 1400.0) damage = (int) (damage * 2 / 3); else if (dist > 1400.0) damage = (int) (damage * 1 / 2); } //gi.cprintf(targ, PRINT_HIGH, "z_rel is %f\n leg: %f stomach: %f chest: %f\n", z_rel, LEG_DAMAGE, STOMACH_DAMAGE, CHEST_DAMAGE ); //gi.cprintf(targ, PRINT_HIGH, "point[2]: %f targ->s.origin[2]: %f height: %d\n", point[2], targ->s.origin[2], height ); //gi.cprintf(targ, PRINT_HIGH, "abs(trag->min[2]): %d targ_max[2] %d\n", (int)abs(targ->mins[2]), (int)targ_maxs2); //gi.cprintf(attacker, PRINT_HIGH, "abs(trag->min[2]): %d targ_max[2] %d\n", (int)abs(targ->mins[2]), (int)targ_maxs2); //gi.cprintf(attacker, PRINT_HIGH, "abs(trag->min[0]): %d targ_max[0] %d\n", (int)abs(targ->mins[0]), (int)targ->maxs[0]); //gi.cprintf(attacker, PRINT_HIGH, "abs(trag->min[1]): %d targ_max[1] %d\n", (int)abs(targ->mins[1]), (int)targ->maxs[1]); if (from_top < 2 * HEAD_HEIGHT) { vec3_t new_point; VerifyHeadShot (point, dir, HEAD_HEIGHT, new_point); VectorSubtract (new_point, targ->s.origin, new_point); //gi.cprintf(attacker, PRINT_HIGH, "z: %d y: %d x: %d\n", (int)(targ_maxs2 - new_point[2]),(int)(new_point[1]) , (int)(new_point[0]) ); if ((targ_maxs2 - new_point[2]) < HEAD_HEIGHT && (abs (new_point[1])) < HEAD_HEIGHT * .8 && (abs (new_point[0])) < HEAD_HEIGHT * .8) { head_success = 1; } } if (head_success) { if (attacker->client) { if (!teamplay->value || team_round_going || stats_afterround->value) { attacker->client->resp.stats_headshot[mod]++; } //AQ2:TNG Slicer Last Damage Location if (INV_AMMO(targ, HELM_NUM)) { attacker->client->resp.last_damaged_part = LOC_KVLR_HELMET; if ((!teamplay->value || team_round_going || stats_afterround->value)) attacker->client->resp.stats_locations[LOC_KVLR_HELMET]++; } else { attacker->client->resp.last_damaged_part = LOC_HDAM; if ((!teamplay->value || team_round_going || stats_afterround->value)) attacker->client->resp.stats_locations[LOC_HDAM]++; } //AQ2:TNG END if (!OnSameTeam (targ, attacker)) attacker->client->resp.hs_streak++; // AQ:TNG Igor[Rock] changing sound dir if (attacker->client->resp.hs_streak == 3) { if (use_rewards->value) { sprintf (buf, "ACCURACY %s!", attacker->client->pers.netname); CenterPrintAll (buf); gi.sound (&g_edicts[0], CHAN_VOICE | CHAN_NO_PHS_ADD, gi.soundindex ("tng/accuracy.wav"), 1.0, ATTN_NONE, 0.0); } attacker->client->resp.hs_streak = 0; } // end of changing sound dir } if (INV_AMMO(targ, HELM_NUM) && mod != MOD_KNIFE && mod != MOD_KNIFE_THROWN && mod != MOD_SNIPER) { if (attacker->client) { gi.cprintf (attacker, PRINT_HIGH, "%s has a Kevlar Helmet - AIM FOR THE BODY!\n", targ->client->pers.netname); gi.cprintf (targ, PRINT_HIGH, "Kevlar Helmet absorbed a part of %s's shot\n", attacker->client->pers.netname); } gi.sound (targ, CHAN_ITEM, gi.soundindex("misc/vest.wav"), 1, ATTN_NORM, 0); damage = (int) (damage / 2); damage_type = LOC_HDAM; bleeding = 0; instant_dam = 1; stopAP = 1; do_sparks = 1; } else if (INV_AMMO(targ, HELM_NUM) && mod == MOD_SNIPER) { if (attacker->client) { gi.cprintf (attacker, PRINT_HIGH, "%s has a Kevlar Helmet, too bad you have AP rounds...\n", targ->client->pers.netname); gi.cprintf (targ, PRINT_HIGH, "Kevlar Helmet absorbed some of %s's AP sniper round\n", attacker->client->pers.netname); } damage = (int) (damage * 0.325); gi.sound (targ, CHAN_VOICE, gi.soundindex("misc/headshot.wav"), 1, ATTN_NORM, 0); damage_type = LOC_HDAM; } else { damage = damage * 1.8 + 1; gi.cprintf (targ, PRINT_HIGH, "Head damage\n"); if (attacker->client) gi.cprintf (attacker, PRINT_HIGH, "You hit %s in the head\n", targ->client->pers.netname); damage_type = LOC_HDAM; if (mod != MOD_KNIFE && mod != MOD_KNIFE_THROWN) gi.sound (targ, CHAN_VOICE, gi.soundindex ("misc/headshot.wav"), 1, ATTN_NORM, 0); //else // gi.sound(targ, CHAN_VOICE, gi.soundindex("misc/glurp.wav"), 1, ATTN_NORM, 0); } } else if (z_rel < LEG_DAMAGE) { damage = damage * .25; gi.cprintf (targ, PRINT_HIGH, "Leg damage\n"); if (attacker->client) { attacker->client->resp.hs_streak = 0; gi.cprintf (attacker, PRINT_HIGH, "You hit %s in the legs\n", targ->client->pers.netname); } damage_type = LOC_LDAM; if (!heroes->value || targ->client->resp.team == 2) { // ESJ Heroes don't run out targ->client->leg_damage = 1; targ->client->leghits++; } //AQ2:TNG Slicer Last Damage Location attacker->client->resp.last_damaged_part = LOC_LDAM; //AQ2:TNG END if (!teamplay->value || team_round_going || stats_afterround->value) attacker->client->resp.stats_locations[LOC_LDAM]++; // TNG Stats } else if (z_rel < STOMACH_DAMAGE) { damage = damage * .4; gi.cprintf (targ, PRINT_HIGH, "Stomach damage\n"); if (attacker->client) { attacker->client->resp.hs_streak = 0; gi.cprintf (attacker, PRINT_HIGH, "You hit %s in the stomach\n", targ->client->pers.netname); } damage_type = LOC_SDAM; //TempFile bloody gibbing if (mod == MOD_SNIPER && sv_gib->value) ThrowGib (targ, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); //AQ2:TNG Slicer Last Damage Location attacker->client->resp.last_damaged_part = LOC_SDAM; //AQ2:TNG END if (!teamplay->value || team_round_going || stats_afterround->value) attacker->client->resp.stats_locations[LOC_SDAM]++; // TNG Stats } else //(z_rel < CHEST_DAMAGE) { if (attacker->client) { attacker->client->resp.hs_streak = 0; } if (INV_AMMO(targ, KEV_NUM) && mod != MOD_KNIFE && mod != MOD_KNIFE_THROWN && mod != MOD_SNIPER) { if (attacker->client) { gi.cprintf (attacker, PRINT_HIGH, "%s has a Kevlar Vest - AIM FOR THE HEAD!\n", targ->client->pers.netname); gi.cprintf (targ, PRINT_HIGH, "Kevlar Vest absorbed most of %s's shot\n", attacker->client->pers.netname); /* if (IsFemale(targ)) gi.cprintf(attacker, PRINT_HIGH, "You bruised %s through her Kevlar Vest\n", targ->client->pers.netname); else gi.cprintf(attacker, PRINT_HIGH, "You bruised %s through his Kevlar Vest\n", targ->client->pers.netname); */ } gi.sound (targ, CHAN_ITEM, gi.soundindex ("misc/vest.wav"), 1, ATTN_NORM, 0); damage = (int) (damage / 10); damage_type = LOC_CDAM; bleeding = 0; instant_dam = 1; stopAP = 1; do_sparks = 1; } else if (INV_AMMO(targ, KEV_NUM) && mod == MOD_SNIPER) { if (attacker->client) { gi.cprintf (attacker, PRINT_HIGH, "%s has a Kevlar Vest, too bad you have AP rounds...\n", targ->client->pers.netname); gi.cprintf (targ, PRINT_HIGH, "Kevlar Vest absorbed some of %s's AP sniper round\n", attacker->client->pers.netname); } damage = damage * .325; damage_type = LOC_CDAM; } else { damage = damage * .65; gi.cprintf (targ, PRINT_HIGH, "Chest damage\n"); if (attacker->client) gi.cprintf (attacker, PRINT_HIGH, "You hit %s in the chest\n", targ->client->pers.netname); damage_type = LOC_CDAM; //TempFile bloody gibbing if (mod == MOD_SNIPER && sv_gib->value) ThrowGib (targ, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } //AQ2:TNG Slicer Last Damage Location if (INV_AMMO(targ, KEV_NUM) && mod != MOD_KNIFE && mod != MOD_KNIFE_THROWN) { attacker->client->resp.last_damaged_part = LOC_KVLR_VEST; if (!teamplay->value || team_round_going || stats_afterround->value) attacker->client->resp.stats_locations[LOC_KVLR_VEST]++; // TNG Stats } else { attacker->client->resp.last_damaged_part = LOC_CDAM; if (!teamplay->value || team_round_going || stats_afterround->value) attacker->client->resp.stats_locations[LOC_CDAM]++; // TNG Stats } //AQ2:TNG END } /*else { // no mod to damage gi.cprintf(targ, PRINT_HIGH, "Head damage\n"); if (attacker->client) gi.cprintf(attacker, PRINT_HIGH, "You hit %s in the head\n", targ->client->pers.netname); damage_type = LOC_HDAM; gi.sound(targ, CHAN_VOICE, gi.soundindex("misc/headshot.wav"), 1, ATTN_NORM, 0); } */ } if (team_round_going && attacker->client && targ != attacker && OnSameTeam (targ, attacker)) { Add_TeamWound (attacker, targ, mod); } } } if (damage_type && !instant_dam) // bullets but not vest hits { vec3_t temp; vec3_t temporig; //vec3_t forward; VectorMA (targ->s.origin, 50, dir, temp); //AngleVectors (attacker->client->v_angle, forward, NULL, NULL); VectorScale (dir, 20, temp); VectorAdd (point, temp, temporig); if (mod != MOD_SNIPER) spray_blood (targ, temporig, dir, damage, mod); else spray_sniper_blood (targ, temporig, dir); } if (mod == MOD_FALLING && !(targ->flags & FL_GODMODE) ) { if (!heroes->value || targ->client->resp.team == 2) { // ESJ no limp for heroes if (targ->client && targ->health > 0) { gi.cprintf (targ, PRINT_HIGH, "Leg damage\n"); targ->client->leg_damage = 1; targ->client->leghits++; // bleeding = 1; for testing } } } if (heroes->value && targ->client && targ->client->resp.team == 1) //ESJ take damage or give points, depending { if (attacker->client) //not fall damage or the like { attacker->client->points += damage; while (attacker->client->points >= 100) { attacker->client->resp.score++; attacker->client->points -= 100; } } damage = 0; } // friendly fire avoidance // if enabled you can't hurt teammates (but you can hurt yourself) // knockback still occurs if (targ != attacker && ((deathmatch->value && ((int)dmflags->value & (DF_MODELTEAMS | DF_SKINTEAMS))) || coop->value)) { if (OnSameTeam (targ, attacker)) { if ((int)dmflags->value & DF_NO_FRIENDLY_FIRE && (team_round_going || !ff_afterround->value)) damage = 0; else mod |= MOD_FRIENDLY_FIRE; } } meansOfDeath = mod; locOfDeath = damage_type; // location client = targ->client; if (dflags & DAMAGE_BULLET) te_sparks = TE_BULLET_SPARKS; else te_sparks = TE_SPARKS; VectorNormalize (dir); // bonus damage for suprising a monster // if (!(dflags & DAMAGE_RADIUS) && (targ->svflags & SVF_MONSTER) && (attacker->client) && (!targ->enemy) && (targ->health > 0)) // damage *= 2; if (targ->flags & FL_NO_KNOCKBACK) knockback = 0; // figure momentum add if (!(dflags & DAMAGE_NO_KNOCKBACK)) { if ((knockback) && (targ->movetype != MOVETYPE_NONE) && (targ->movetype != MOVETYPE_BOUNCE) && (targ->movetype != MOVETYPE_PUSH) && (targ->movetype != MOVETYPE_STOP)) { vec3_t kvel, flydir; float mass; if (mod != MOD_FALLING) { VectorCopy (dir, flydir); flydir[2] += 0.4f; } if (targ->mass < 50) mass = 50; else mass = targ->mass; if (targ->client && attacker == targ) VectorScale (flydir, 1600.0 * (float) knockback / mass, kvel); // the rocket jump hack... else VectorScale (flydir, 500.0 * (float) knockback / mass, kvel); // FB //if (mod == MOD_KICK ) //{ // kvel[2] = 0; //} VectorAdd (targ->velocity, kvel, targ->velocity); } } take = damage; save = 0; // check for godmode if ((targ->flags & FL_GODMODE) && !(dflags & DAMAGE_NO_PROTECTION)) { take = 0; save = damage; SpawnDamage (te_sparks, point, normal, save); } // zucc don't need this stuff, but to remove it need to change how damagefeedback works with colors // check for invincibility if ((client && client->invincible_framenum > level.framenum) && !(dflags & DAMAGE_NO_PROTECTION)) { if (targ->pain_debounce_time < level.time) { gi.sound (targ, CHAN_ITEM, gi.soundindex ("items/protect4.wav"), 1, ATTN_NORM, 0); targ->pain_debounce_time = level.time + 2; } take = 0; save = damage; } psave = CheckPowerArmor (targ, point, normal, take, dflags); take -= psave; asave = CheckArmor (targ, point, normal, take, te_sparks, dflags); take -= asave; //treat cheat/powerup savings the same as armor asave += save; // team damage avoidance if (!(dflags & DAMAGE_NO_PROTECTION) && CheckTeamDamage (targ, attacker)) return; if ((mod == MOD_M3) || (mod == MOD_HC) || (mod == MOD_HELD_GRENADE) || (mod == MOD_HG_SPLASH) || (mod == MOD_G_SPLASH) || (mod == MOD_BREAKINGGLASS)) { //FB 6/3/99 - shotgun damage report stuff int playernum = targ - g_edicts; playernum--; if (playernum >= 0 && playernum <= game.maxclients - 1) *(took_damage + playernum) = 1; //FB 6/3/99 bleeding = 1; instant_dam = 0; } /* if ( (mod == MOD_M3) || (mod == MOD_HC) ) { instant_dam = 1; remain = take % 2; take = (int)(take/2); // balances out difference in how action and axshun handle damage/bleeding } */ if (ctf->value) CTFCheckHurtCarrier (targ, attacker); // do the damage if (take) { // zucc added check for stopAP, if it hit a vest we want sparks if (((targ->svflags & SVF_MONSTER) || (client)) && !do_sparks) SpawnDamage (TE_BLOOD, point, normal, take); else SpawnDamage (te_sparks, point, normal, take); // all things that have at least some instantaneous damage, i.e. bruising/falling if (instant_dam) targ->health = targ->health - take; if (targ->health <= 0) { if (client && attacker->client) { //Added these here also, if this is the last shot and before shots is from //different attacker, msg's would go to wrong client -M if (!OnSameTeam (attacker, targ)) attacker->client->resp.damage_dealt += damage; client->attacker = attacker; client->attacker_mod = mod; client->attacker_loc = damage_type; } if ((targ->svflags & SVF_MONSTER) || (client)) targ->flags |= FL_NO_KNOCKBACK; Killed (targ, inflictor, attacker, take, point); return; } } if (targ->svflags & SVF_MONSTER) { M_ReactToDamage (targ, attacker); if (!(targ->monsterinfo.aiflags & AI_DUCKED) && (take)) { targ->pain (targ, attacker, knockback, take); // nightmare mode monsters don't go into pain frames often if (skill->value == 3) targ->pain_debounce_time = level.time + 5; } } else if (client) { if (!(targ->flags & FL_GODMODE) && (take)) targ->pain (targ, attacker, knockback, take); } else if (take) { if (targ->pain) targ->pain (targ, attacker, knockback, take); } // add to the damage inflicted on a player this frame // the total will be turned into screen blends and view angle kicks // at the end of the frame if (client) { client->damage_parmor += psave; client->damage_armor += asave; client->damage_blood += take; client->damage_knockback += knockback; //zucc handle adding bleeding here if (damage_type && bleeding) // one of the hit location weapons { /* zucc add in partial bleeding, changed if ( client->bleeding < 4*damage*BLEED_TIME ) { client->bleeding = 4*damage*BLEED_TIME + client->bleeding/2; } else { client->bleeding += damage*BLEED_TIME*2; } */ client->bleeding += damage * BLEED_TIME; VectorSubtract (point, targ->absmax, targ->client->bleedloc_offset); //VectorSubtract(point, targ->s.origin, client->bleedloc_offset); } else if (bleeding) { /* if ( client->bleeding < damage*BLEED_TIME ) { client->bleeding = damage*BLEED_TIME; //client->bleedcount = 0; } */ client->bleeding += damage * BLEED_TIME; VectorSubtract (point, targ->absmax, targ->client->bleedloc_offset); //VectorSubtract(point, targ->s.origin, client->bleedloc_offset); } if (attacker->client) { if (!OnSameTeam (attacker, targ)) attacker->client->resp.damage_dealt += damage; client->attacker = attacker; client->attacker_mod = mod; client->attacker_loc = damage_type; client->push_timeout = 50; //VectorCopy(dir, client->bleeddir ); //VectorCopy(point, client->bleedpoint ); //VectorCopy(normal, client->bleednormal); } VectorCopy (point, client->damage_from); } }
/* ================== player_die ================== */ void player_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { int n; VectorClear (self->avelocity); self->takedamage = DAMAGE_YES; self->movetype = MOVETYPE_TOSS; self->s.modelindex2 = 0; // remove linked weapon model //ZOID self->s.modelindex3 = 0; // remove linked ctf flag //ZOID self->s.angles[0] = 0; self->s.angles[2] = 0; self->s.sound = 0; self->client->weapon_sound = 0; self->maxs[2] = -8; // self->solid = SOLID_NOT; self->svflags |= SVF_DEADMONSTER; if (!self->deadflag) { self->client->respawn_time = level.time + 1.0; LookAtKiller (self, inflictor, attacker); self->client->ps.pmove.pm_type = PM_DEAD; ClientObituary (self, inflictor, attacker); //ZOID CTFFragBonuses(self, inflictor, attacker); //ZOID TossClientWeapon (self); //ZOID CTFPlayerResetGrapple(self); CTFDeadDropFlag(self); CTFDeadDropTech(self); //ZOID if (deathmatch->value && !self->client->showscores) Cmd_Help_f (self); // show scores } // remove powerups self->client->quad_framenum = 0; self->client->invincible_framenum = 0; self->client->breather_framenum = 0; self->client->enviro_framenum = 0; // clear inventory memset(self->client->pers.inventory, 0, sizeof(self->client->pers.inventory)); if (self->health < -40) { // gib gi.sound (self, CHAN_BODY, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n= 0; n < 4; n++) ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); ThrowClientHead (self, damage); //ZOID self->client->anim_priority = ANIM_DEATH; self->client->anim_end = 0; //ZOID self->takedamage = DAMAGE_NO; } else { // normal death if (!self->deadflag) { static int i; i = (i+1)%3; // start a death animation self->client->anim_priority = ANIM_DEATH; if (self->client->ps.pmove.pm_flags & PMF_DUCKED) { self->s.frame = FRAME_crdeath1-1; self->client->anim_end = FRAME_crdeath5; } else switch (i) { case 0: self->s.frame = FRAME_death101-1; self->client->anim_end = FRAME_death106; break; case 1: self->s.frame = FRAME_death201-1; self->client->anim_end = FRAME_death206; break; case 2: self->s.frame = FRAME_death301-1; self->client->anim_end = FRAME_death308; break; } gi.sound (self, CHAN_VOICE, gi.soundindex(va("*death%i.wav", (rand()%4)+1)), 1, ATTN_NORM, 0); } } self->deadflag = DEAD_DEAD; gi.linkentity (self); }
void BossExplode (edict_t *self) { vec3_t org; int n; self->think = BossExplode; VectorCopy (self->s.origin, org); org[2] += 24 + (rand()&15); switch (self->count++) { case 0: org[0] -= 24; org[1] -= 24; break; case 1: org[0] += 24; org[1] += 24; break; case 2: org[0] += 24; org[1] -= 24; break; case 3: org[0] -= 24; org[1] += 24; break; case 4: org[0] -= 48; org[1] -= 48; break; case 5: org[0] += 48; org[1] += 48; break; case 6: org[0] -= 48; org[1] += 48; break; case 7: org[0] += 48; org[1] -= 48; break; case 8: self->s.sound = 0; for (n= 0; n < 4; n++) ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", 500, GIB_ORGANIC); for (n= 0; n < 8; n++) ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", 500, GIB_METALLIC); ThrowGib (self, "models/objects/gibs/chest/tris.md2", 500, GIB_ORGANIC); ThrowHead (self, "models/objects/gibs/gear/tris.md2", 500, GIB_METALLIC); self->deadflag = DEAD_DEAD; return; } gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_EXPLOSION1); gi.WritePosition (org); gi.multicast (self->s.origin, MULTICAST_PVS); self->nextthink = level.time + 0.1; }
void m_soldier_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { int n; // notify the owner that the monster is dead M_Notify(self); #ifdef OLD_NOLAG_STYLE // reduce lag by removing the entity right away if (nolag->value) { M_Remove(self, false, true); return; } #endif // check for gib if (self->health <= self->gib_health) { gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n= 0; n < 2; n++) ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); for (n= 0; n < 4; n++) ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); //ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); //self->deadflag = DEAD_DEAD; #ifdef OLD_NOLAG_STYLE M_Remove(self, false, false); #else if (nolag->value) M_Remove(self, false, true); else M_Remove(self, false, false); #endif return; } if (self->deadflag == DEAD_DEAD) return; // regular death gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); self->takedamage = DAMAGE_YES; self->deadflag = DEAD_DEAD; n = GetRandom(1, 6); switch (n) { case 1: self->monsterinfo.currentmove = &m_soldier_move_death1; break; case 2: self->monsterinfo.currentmove = &m_soldier_move_death2; break; case 3: self->monsterinfo.currentmove = &m_soldier_move_death3; break; case 4: self->monsterinfo.currentmove = &m_soldier_move_death4; break; case 5: self->monsterinfo.currentmove = &m_soldier_move_death5; break; case 6: self->monsterinfo.currentmove = &m_soldier_move_death6; break; } DroneList_Remove(self); if (self->activator && !self->activator->client) { self->activator->num_monsters_real--; // gi.bprintf(PRINT_HIGH, "releasing %p (%d)\n", self, self->activator->num_monsters_real); } }
void widow2_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; int clipped; if (!self) { return; } /* check for gib */ if (self->health <= self->gib_health) { clipped = min(damage, 100); gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/bone/tris.md2", clipped, GIB_ORGANIC, NULL, false); } for (n = 0; n < 3; n++) { ThrowWidowGibLoc(self, "models/objects/gibs/sm_meat/tris.md2", clipped, GIB_ORGANIC, NULL, false); } for (n = 0; n < 3; n++) { ThrowWidowGibSized(self, "models/monsters/blackwidow2/gib1/tris.md2", clipped, GIB_METALLIC, NULL, 0, false); ThrowWidowGibSized(self, "models/monsters/blackwidow2/gib2/tris.md2", clipped, GIB_METALLIC, NULL, gi.soundindex("misc/fhit3.wav"), false); } for (n = 0; n < 2; n++) { ThrowWidowGibSized(self, "models/monsters/blackwidow2/gib3/tris.md2", clipped, GIB_METALLIC, NULL, 0, false); ThrowWidowGibSized(self, "models/monsters/blackwidow/gib3/tris.md2", clipped, GIB_METALLIC, NULL, 0, false); } ThrowGib(self, "models/objects/gibs/chest/tris.md2", clipped, GIB_ORGANIC); ThrowHead(self, "models/objects/gibs/head2/tris.md2", clipped, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } gi.sound(self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0); self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_NO; self->count = 0; KillChildren(self); self->monsterinfo.quad_framenum = 0; self->monsterinfo.double_framenum = 0; self->monsterinfo.invincible_framenum = 0; self->monsterinfo.currentmove = &widow2_move_death; }
void chick_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /*unused */) { int n; if (!self) { return; } /* check for gib */ if (self->health <= self->gib_health) // if (damage >= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 4; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage*2, GIB_ORGANIC); } for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/sm_metal/tris.md2", damage*2, GIB_METALLIC); } // ace - TEST: shouldn't be too taxing for (n = 0; n < 4; n++) { ThrowGib(self, "sprites/null.sp2", 512, GIB_ORGANIC); } // ace - TEST: shouldn't be too taxing for (n = 0; n < 4; n++) { ThrowGib(self, "sprites/null.sp2", 512, GIB_METALLIC); } ThrowHead(self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->svflags |= SVF_DEADMONSTER; // moved this here for "smaller" enemies n = randk() % 2; if (n == 0) { self->monsterinfo.currentmove = &chick_move_death1; gi.sound(self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0); } else { self->monsterinfo.currentmove = &chick_move_death2; gi.sound(self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0); } }
void mychick_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) { int n; M_Notify(self); // reduce lag by removing the entity right away #ifdef OLD_NOLAG_STYLE if (nolag->value) { M_Remove(self, false, true); return; } #endif // check for gib if (self->health <= self->gib_health) { gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); for (n= 0; n < 2; n++) ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); for (n= 0; n < 4; n++) ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); //ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); //self->deadflag = DEAD_DEAD; #ifdef OLD_NOLAG_STYLE M_Remove(self, false, false); #else if (nolag->value) M_Remove(self, false, true); else M_Remove(self, false, false); #endif return; } if (self->deadflag == DEAD_DEAD) return; // regular death self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; //level.total_monsters--; n = rand() % 2; if (n == 0) { self->monsterinfo.currentmove = &mychick_move_death1; gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0); } else { self->monsterinfo.currentmove = &mychick_move_death2; gi.sound (self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0); } DroneList_Remove(self); if (self->activator && !self->activator->client) { self->activator->num_monsters_real--; // gi.bprintf(PRINT_HIGH, "releasing %p (%d)\n", self, self->activator->num_monsters_real); } }
void hover_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, int damage, vec3_t point /* unused */) { int n; if (!self) { return; } /* check for gib */ if (self->health <= self->gib_health) { gi.sound(self, CHAN_VOICE, gi.soundindex( "misc/udeath.wav"), 1, ATTN_NORM, 0); for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); } for (n = 0; n < 2; n++) { ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); } ThrowHead(self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); self->deadflag = DEAD_DEAD; return; } if (self->deadflag == DEAD_DEAD) { return; } /* regular death */ if (random() < 0.5) { gi.sound(self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0); } else { gi.sound(self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0); } self->deadflag = DEAD_DEAD; self->takedamage = DAMAGE_YES; self->monsterinfo.currentmove = &hover_move_death1; }