void target_earthquake_think (edict_t *self) { int i; edict_t *e; if (self->pain_debounce_framenum < level.framenum) { gi.positioned_sound (self->s.origin, self, CHAN_AUTO, self->noise_index, 1.0f, ATTN_NONE, 0); self->pain_debounce_framenum = level.framenum + SECS_TO_FRAMES(0.5f); } for (i=1, e=g_edicts+i; i < globals.num_edicts; i++,e++) { if (!e->inuse) continue; if (!e->client) continue; if (!e->groundentity) continue; e->groundentity = NULL; e->velocity[0] += crandom()* 150; e->velocity[1] += crandom()* 150; e->velocity[2] = self->speed * (100.0f / e->mass); } if (level.framenum < self->damage_debounce_framenum) self->nextthink = level.framenum + SECS_TO_FRAMES(0.1f); }
void target_earthquake_use (edict_t *self, edict_t *other, edict_t *activator) { self->damage_debounce_framenum = level.framenum + SECS_TO_FRAMES(self->count); self->nextthink = level.framenum + SECS_TO_FRAMES(0.1f); self->activator = activator; self->pain_debounce_framenum = 0; }
/** * Resend the entire statusbar string to update the hud. * */ void TDM_UpdateHud(edict_t *ent, qboolean force) { if (!ent->client) return; if (!force) { if (g_weapon_hud->value == 0) { return; } if (!ent->client->next_hud_update) { return; } // too soon, can only send statusbar at most once every 2 seconds if ((level.framenum - ent->client->last_hud_update) < SECS_TO_FRAMES(2.0F)) { return; } // not time yet if (ent->client->next_hud_update > level.framenum) { return; } } if (ent->client->pers.team == TEAM_SPEC) { TDM_SendSpectatorStatusBar(ent); } else if (ent->client->pers.team > TEAM_SPEC) { TDM_SendPlayerStatusBar(ent); } // set next update to way in the future so it's basically never automatically updated. ent->client->next_hud_update = 0; ent->client->last_hud_update = level.framenum; }
void hurt_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { int dflags; if (!other->takedamage) return; if (self->touch_debounce_framenum > level.framenum) return; if (self->spawnflags & 16) self->touch_debounce_framenum = level.framenum + SECS_TO_FRAMES(1); else self->touch_debounce_framenum = level.framenum + 1; if (!(self->spawnflags & 4)) { if ((level.framenum % 10) == 0) gi.sound (other, CHAN_AUTO, self->noise_index, 1, ATTN_NORM, 0); } if (self->spawnflags & 8) dflags = DAMAGE_NO_PROTECTION; else dflags = 0; T_Damage (other, self, self, vec3_origin, other->s.origin, vec3_origin, self->dmg, self->dmg, dflags, MOD_TRIGGER_HURT); }
void SP_target_crosslevel_target (edict_t *self) { if (! self->delay) self->delay = 1; self->svflags = SVF_NOCLIENT; self->think = target_crosslevel_target_think; self->nextthink = level.framenum + SECS_TO_FRAMES(self->delay); }
void weapon_grenade_fire (edict_t *ent, qboolean held) { vec3_t offset; vec3_t forward, right; vec3_t start; int damage = 125; float timer; int speed; float radius; radius = damage+40; if (is_quad) { //r1: prevent quad on someone making grenades into quad grenades on death explode if (is_quad == ent || g_bugs->value >= 1) damage *= 4; } VectorSet(offset, 8, 8, ent->viewheight-8); AngleVectors (ent->client->v_angle, forward, right, NULL); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); timer = (ent->client->grenade_framenum - level.framenum) * FRAMETIME; speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER); fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held); TDM_WeaponFired (ent); if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->inventory[ent->client->ammo_index]--; ent->client->grenade_framenum = level.framenum + SECS_TO_FRAMES(1); if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses { return; } if (ent->health <= 0) return; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->client->anim_priority = ANIM_ATTACK; ent->s.frame = FRAME_crattak1-1; ent->client->anim_end = FRAME_crattak3; } else { ent->client->anim_priority = ANIM_REVERSE; ent->s.frame = FRAME_wave08; ent->client->anim_end = FRAME_wave01; } }
void use_target_explosion (edict_t *self, edict_t *other, edict_t *activator) { self->activator = activator; if (!self->delay) { target_explosion_explode (self); return; } self->think = target_explosion_explode; self->nextthink = level.framenum + SECS_TO_FRAMES(self->delay); }
// the trigger was just activated // ent->activator should be set to the activator so it can be held through a delay // so wait for the delay time before firing void multi_trigger (edict_t *ent) { if (ent->nextthink) return; // already been triggered G_UseTargets (ent, ent->activator); if (ent->wait > 0) { ent->think = multi_wait; ent->nextthink = level.framenum + SECS_TO_FRAMES(ent->wait); } else { // we can't just remove (self) here, because this is a touch function // called while looping through area links... ent->touch = NULL; ent->nextthink = level.framenum + 1; ent->think = G_FreeEdict; } }
/* ================= Think_Weapon Called by ClientBeginServerFrame and ClientThink ================= */ void Think_Weapon (edict_t *ent) { // if just died, put the weapon away if (ent->health < 1) { ent->client->newweapon = NULL; ChangeWeapon (ent); } // don't run weapons at all during timeout, preserve reload frame etc if (tdm_match_status == MM_TIMEOUT) return; //r1: don't allow any attack during countdown if (tdm_match_status == MM_COUNTDOWN) { ent->client->buttons &= ~BUTTON_ATTACK; ent->client->latched_buttons &= ~BUTTON_ATTACK; } // variable FPS support if (ent->client->next_weapon_think > level.framenum) return; ent->client->next_weapon_think = level.framenum + (SECS_TO_FRAMES(0.1f)); // call active weapon think routine if (ent->client->weapon && ent->client->weapon->weaponthink) { if (ent->client->quad_framenum > level.framenum) is_quad = ent; else is_quad = NULL; if (ent->client->silencer_shots) is_silenced = MZ_SILENCED; else is_silenced = 0; ent->client->weapon->weaponthink (ent); } }
void trigger_push_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { if (other->enttype == ENT_GRENADE) { VectorScale (self->movedir, self->speed * 10, other->velocity); } else if (other->health > 0) { VectorScale (self->movedir, self->speed * 10, other->velocity); if (other->client) { // don't take falling damage immediately from this VectorCopy (other->velocity, other->client->oldvelocity); if (other->fly_sound_debounce_framenum < level.framenum) { other->fly_sound_debounce_framenum = level.framenum + SECS_TO_FRAMES(1.5f); gi.sound (other, CHAN_AUTO, windsound, 1, ATTN_NORM, 0); } } } if (self->spawnflags & PUSH_ONCE) G_FreeEdict (self); }
void Machinegun_Fire (edict_t *ent) { int i; vec3_t start; vec3_t forward, right; vec3_t angles; int damage = 8; int kick = 2; vec3_t offset; if (!(ent->client->buttons & BUTTON_ATTACK)) { ent->client->machinegun_shots = 0; ent->client->ps.gunframe++; return; } if (ent->client->ps.gunframe == 5) ent->client->ps.gunframe = 4; else ent->client->ps.gunframe = 5; if (ent->client->inventory[ent->client->ammo_index] < 1) { ent->client->ps.gunframe = 6; if (level.framenum >= ent->pain_debounce_framenum) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_framenum = level.framenum + SECS_TO_FRAMES(1); } NoAmmoWeaponChange (ent); return; } if (is_quad == ent) { damage *= 4; kick *= 4; } for (i=1 ; i<3 ; i++) { ent->client->kick_origin_final[i] = crandom() * 0.35f; ent->client->kick_angles_final[i] = crandom() * 0.7f; } ent->client->kick_origin_final[0] = crandom() * 0.35f; ent->client->kick_angles_final[0] = ent->client->machinegun_shots * -1.5f; ent->client->kick_origin_start = 0; ent->client->kick_origin_end = 0.1f * SERVER_FPS; // get start / end positions VectorAdd (ent->client->v_angle, ent->client->kick_angles_final, angles); AngleVectors (angles, forward, right, NULL); VectorSet(offset, 0, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN); TDM_WeaponFired (ent); gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_MACHINEGUN | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->inventory[ent->client->ammo_index]--; ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - (int) (random()+0.25f); ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - (int) (random()+0.25f); ent->client->anim_end = FRAME_attack8; } }
void Weapon_Grenade (edict_t *ent) { if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY)) { ChangeWeapon (ent); return; } if (ent->client->weaponstate == WEAPON_ACTIVATING) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = 16; return; } if (ent->client->weaponstate == WEAPON_READY) { if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) { ent->client->latched_buttons &= ~BUTTON_ATTACK; if (ent->client->inventory[ent->client->ammo_index]) { ent->client->ps.gunframe = 1; ent->client->weaponstate = WEAPON_FIRING; ent->client->grenade_framenum = 0; } else { if (level.framenum >= ent->pain_debounce_framenum) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_framenum = level.framenum + SECS_TO_FRAMES(1); } NoAmmoWeaponChange (ent); } return; } if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48)) { if (genrand_int32()&15) return; } if (++ent->client->ps.gunframe > 48) ent->client->ps.gunframe = 16; return; } if (ent->client->weaponstate == WEAPON_FIRING) { if (ent->client->ps.gunframe == 5) gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0); if (ent->client->ps.gunframe == 11) { if (!ent->client->grenade_framenum) { ent->client->grenade_framenum = level.framenum + SECS_TO_FRAMES(GRENADE_TIMER + 0.2f); ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav"); } // they waited too long, detonate it in their hand if (ent->client->grenade_state != GRENADE_BLEW_UP && level.framenum >= ent->client->grenade_framenum) { ent->client->weapon_sound = 0; weapon_grenade_fire (ent, true); ent->client->grenade_state = GRENADE_BLEW_UP; } if (ent->client->buttons & BUTTON_ATTACK) return; if (ent->client->grenade_state == GRENADE_BLEW_UP) { if (level.framenum >= ent->client->grenade_framenum) { ent->client->ps.gunframe = 15; ent->client->grenade_state = GRENADE_NONE; } else { return; } } } if (ent->client->ps.gunframe == 12) { ent->client->weapon_sound = 0; weapon_grenade_fire (ent, false); ent->client->grenade_state = GRENADE_THROWN; } if ((ent->client->ps.gunframe == 15) && (level.framenum < ent->client->grenade_framenum)) return; ent->client->ps.gunframe++; if (ent->client->ps.gunframe == 16) { ent->client->grenade_framenum = 0; ent->client->grenade_state = GRENADE_NONE; ent->client->weaponstate = WEAPON_READY; } } }
void Weapon_HyperBlaster_Fire (edict_t *ent) { float rotation; vec3_t offset; int effect; int damage; ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav"); if (!(ent->client->buttons & BUTTON_ATTACK)) { ent->client->ps.gunframe++; } else { if (! ent->client->inventory[ent->client->ammo_index] ) { if (level.framenum >= ent->pain_debounce_framenum) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_framenum = level.framenum + SECS_TO_FRAMES(1); } NoAmmoWeaponChange (ent); } else { rotation = (ent->client->ps.gunframe - 5) * 2*M_PI/6; offset[0] = -4 * sin(rotation); offset[1] = 0; offset[2] = 4 * cos(rotation); if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9)) effect = EF_HYPERBLASTER; else effect = 0; damage = 15; Blaster_Fire (ent, offset, damage, true, effect); TDM_WeaponFired (ent); if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->inventory[ent->client->ammo_index]--; ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - 1; ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - 1; ent->client->anim_end = FRAME_attack8; } } ent->client->ps.gunframe++; if (ent->client->ps.gunframe == 12 && ent->client->inventory[ent->client->ammo_index]) ent->client->ps.gunframe = 6; } if (ent->client->ps.gunframe == 12) { gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0); ent->client->weapon_sound = 0; } }
/* ============== TDM_Disconnected ============== A player disconnected, do things. */ void TDM_Disconnected (edict_t *ent) { qboolean removeTimeout; removeTimeout = false; //have to check this right up here since we nuke the teamplayer just below! if (tdm_match_status == MM_TIMEOUT && level.tdm_timeout_caller && level.tdm_timeout_caller->client == ent) removeTimeout = true; //we remove this up here so TDM_LeftTeam doesn't try to resume if we become implicit timeout caller TDM_RemoveStatsLink (ent); if (ent->client->pers.team) { if (tdm_match_status >= MM_PLAYING && tdm_match_status != MM_SCOREBOARD) { //do joincode stuff if a team player disconnects - save all their client info ent->client->resp.teamplayerinfo->saved_client = gi.TagMalloc (sizeof(gclient_t), TAG_GAME); *ent->client->resp.teamplayerinfo->saved_client = *ent->client; ent->client->resp.teamplayerinfo->saved_entity = gi.TagMalloc (sizeof(edict_t), TAG_GAME); *ent->client->resp.teamplayerinfo->saved_entity = *ent; if (TDM_Is1V1() && g_1v1_timeout->value > 0) { edict_t *ghost; //may have already been set by a player or previous client disconnect if (tdm_match_status != MM_TIMEOUT) { edict_t *opponent; //timeout is called implicitly in 1v1 games or the other player would auto win level.timeout_end_framenum = level.realframenum + SECS_TO_FRAMES(g_1v1_timeout->value); level.last_tdm_match_status = tdm_match_status; tdm_match_status = MM_TIMEOUT; level.tdm_timeout_caller = ent->client->resp.teamplayerinfo; gi.bprintf (PRINT_CHAT, "%s disconnected and has %s to reconnect.\n", level.tdm_timeout_caller->name, TDM_SecsToString (g_1v1_timeout->value)); //show the opponent their options opponent = TDM_FindPlayerForTeam (TEAM_A); if (opponent) gi.cprintf (opponent, PRINT_HIGH, "Your opponent has disconnected. You can allow them %s to reconnect, or you can force a forfeit by typing 'win' in the console.\n", TDM_SecsToString (g_1v1_timeout->value)); opponent = TDM_FindPlayerForTeam (TEAM_B); if (opponent) gi.cprintf (opponent, PRINT_HIGH, "Your opponent has disconnected. You can allow them %s to reconnect, or you can force a forfeit by typing 'win' in the console.\n", TDM_SecsToString (g_1v1_timeout->value)); } //show a "ghost" player where the player was ghost = G_Spawn (); VectorCopy (ent->s.origin, ghost->s.origin); VectorCopy (ent->s.origin, ghost->old_origin); VectorCopy (ent->s.angles, ghost->s.angles); ghost->s.effects = EF_SPHERETRANS; ghost->s.modelindex = 255; ghost->s.modelindex2 = 255; ghost->s.skinnum = ent - g_edicts - 1; ghost->s.frame = ent->s.frame; ghost->count = ent->s.number; ghost->classname = "ghost"; ghost->target_ent = ent; ghost->enttype = ENT_GHOST; gi.linkentity (ghost); } } if (removeTimeout) TDM_ResumeGame (); TDM_LeftTeam (ent, false); } TDM_TeamsChanged (); if (tdm_match_status == MM_WARMUP && teaminfo[TEAM_SPEC].players == 0 && teaminfo[TEAM_A].players == 0 && teaminfo[TEAM_B].players == 0) { if (vote.active) TDM_RemoveVote (); //reset the map if it's been running for over 7 days to workaround time precision bugs in the engine, fixes 0000208 if (time (NULL) - level.spawntime > (86400 * 7)) { char command[256]; Com_sprintf (command, sizeof(command), "gamemap \"%s\"\n", level.mapname); gi.AddCommandString (command); } } else TDM_CheckVote (); //zero for connecting clients on server browsers ent->client->ps.stats[STAT_FRAGS] = 0; }
void Weapon_Generic (edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int *pause_frames, int *fire_frames, void (*fire)(edict_t *ent)) { int n; if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses { return; } if (ent->client->weaponstate == WEAPON_DROPPING) { if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST) { ChangeWeapon (ent); return; } else if ((FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe) == 4) { ent->client->anim_priority = ANIM_REVERSE; if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crpain4+1; ent->client->anim_end = FRAME_crpain1; } else { ent->s.frame = FRAME_pain304+1; ent->client->anim_end = FRAME_pain301; } } ent->client->ps.gunframe++; return; } if (ent->client->weaponstate == WEAPON_ACTIVATING) { if (g_fast_weap_switch->value >= 2) ent->client->ps.gunframe = FRAME_ACTIVATE_LAST; if (ent->client->ps.gunframe == FRAME_ACTIVATE_LAST) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = FRAME_IDLE_FIRST; return; } ent->client->ps.gunframe++; return; } if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING)) { ent->client->weaponstate = WEAPON_DROPPING; if (g_fast_weap_switch->value >= 1) { ChangeWeapon (ent); return; } else ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST; if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4) { ent->client->anim_priority = ANIM_REVERSE; if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crpain4+1; ent->client->anim_end = FRAME_crpain1; } else { ent->s.frame = FRAME_pain304+1; ent->client->anim_end = FRAME_pain301; } } return; } if (ent->client->weaponstate == WEAPON_READY) { if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) { ent->client->latched_buttons &= ~BUTTON_ATTACK; if ((!ent->client->ammo_index) || ( ent->client->inventory[ent->client->ammo_index] >= ent->client->weapon->quantity)) { ent->client->ps.gunframe = FRAME_FIRE_FIRST; ent->client->weaponstate = WEAPON_FIRING; // start the animation ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1-1; ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1-1; ent->client->anim_end = FRAME_attack8; } } else { if (level.framenum >= ent->pain_debounce_framenum) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_framenum = level.framenum + SECS_TO_FRAMES(1); } NoAmmoWeaponChange (ent); } } else { if (ent->client->ps.gunframe == FRAME_IDLE_LAST) { ent->client->ps.gunframe = FRAME_IDLE_FIRST; return; } if (pause_frames) { for (n = 0; pause_frames[n]; n++) { if (ent->client->ps.gunframe == pause_frames[n]) { if (genrand_int32()&15) return; } } } ent->client->ps.gunframe++; return; } } if (ent->client->weaponstate == WEAPON_FIRING) { for (n = 0; fire_frames[n]; n++) { if (ent->client->ps.gunframe == fire_frames[n]) { if (ent->client->quad_framenum > level.framenum) gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); fire (ent); break; } } if (!fire_frames[n]) { ent->client->ps.gunframe++; if ((ent->client->newweapon) && g_fast_weap_switch->value >= 3) { ChangeWeapon (ent); return; } } else { if ((ent->client->newweapon) && g_fast_weap_switch->value >= 4) { ChangeWeapon (ent); return; } } if (ent->client->ps.gunframe == FRAME_IDLE_FIRST+1) ent->client->weaponstate = WEAPON_READY; } }
void target_laser_think (edict_t *self) { edict_t *ignore; vec3_t start; vec3_t end; trace_t tr; vec3_t point; vec3_t last_movedir; int count; if (self->spawnflags & 0x80000000) count = 8; else count = 4; if (self->enemy) { VectorCopy (self->movedir, last_movedir); VectorMA (self->enemy->absmin, 0.5f, self->enemy->size, point); VectorSubtract (point, self->s.origin, self->movedir); VectorNormalize (self->movedir); if (!VectorCompare(self->movedir, last_movedir)) self->spawnflags |= 0x80000000; } ignore = self; VectorCopy (self->s.origin, start); VectorMA (start, 2048, self->movedir, end); while(1) { tr = gi.trace (start, NULL, NULL, end, ignore, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER); if (!tr.ent) break; // hurt it if we can if ((tr.ent->takedamage) && !(tr.ent->flags & FL_IMMUNE_LASER)) T_Damage (tr.ent, self, self->activator, self->movedir, tr.endpos, vec3_origin, self->dmg, 1, DAMAGE_ENERGY, MOD_TARGET_LASER); // if we hit something that's not a monster or player or is immune to lasers, we're done if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client)) { if (self->spawnflags & 0x80000000) { self->spawnflags &= ~0x80000000; gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_LASER_SPARKS); gi.WriteByte (count); gi.WritePosition (tr.endpos); gi.WriteDir (tr.plane.normal); gi.WriteByte (self->s.skinnum & 255); gi.multicast (tr.endpos, MULTICAST_PVS); } break; } ignore = tr.ent; VectorCopy (tr.endpos, start); } VectorCopy (tr.endpos, self->s.old_origin); self->nextthink = level.framenum + SECS_TO_FRAMES(0.1f); }
void Chaingun_Fire (edict_t *ent) { int i; int shots; vec3_t start; vec3_t forward, right, up; float r, u; vec3_t offset; int damage; int kick = 2; damage = 6; if (ent->client->ps.gunframe == 5) gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0); if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK)) { ent->client->ps.gunframe = 32; ent->client->weapon_sound = 0; return; } else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK) && ent->client->inventory[ent->client->ammo_index]) { ent->client->ps.gunframe = 15; } else { ent->client->ps.gunframe++; } if (ent->client->ps.gunframe == 22) { ent->client->weapon_sound = 0; gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0); } else { ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav"); } ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1); ent->client->anim_end = FRAME_crattak9; } else { ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1); ent->client->anim_end = FRAME_attack8; } if (ent->client->ps.gunframe <= 9) shots = 1; else if (ent->client->ps.gunframe <= 14) { if (ent->client->buttons & BUTTON_ATTACK) shots = 2; else shots = 1; } else shots = 3; if (ent->client->inventory[ent->client->ammo_index] < shots) shots = ent->client->inventory[ent->client->ammo_index]; if (!shots) { if (level.framenum >= ent->pain_debounce_framenum) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_framenum = level.framenum + SECS_TO_FRAMES(1); } NoAmmoWeaponChange (ent); return; } if (is_quad == ent) { damage *= 4; kick *= 4; } for (i=0 ; i<3 ; i++) { ent->client->kick_origin_final[i] = crandom() * 0.35f; ent->client->kick_angles_final[i] = crandom() * 0.7f; } ent->client->kick_origin_start = 0; ent->client->kick_origin_end = 0.1f * SERVER_FPS; for (i=0 ; i<shots ; i++) { // get start / end positions AngleVectors (ent->client->v_angle, forward, right, up); r = 7 + crandom()*4; u = crandom()*4; VectorSet(offset, 0, r, u + ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN); TDM_WeaponFired (ent); } // send muzzle flash gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ent->client->inventory[ent->client->ammo_index] -= shots; }
void SP_target_laser (edict_t *self) { // let everything else get spawned before we start firing self->think = target_laser_start; self->nextthink = level.framenum + SECS_TO_FRAMES(1); }