void player_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point /* unused */) { int n; if (!self || !inflictor || !attacker) { return; } 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->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", (randk() % 4) + 1)), 1, ATTN_NORM, 0); } } self->deadflag = DEAD_DEAD; gi.linkentity(self); }
/* * A brand new game has been started */ void SV_InitGame ( void ) { int i; edict_t *ent; char idmaster [ 32 ]; if ( svs.initialized ) { /* cause any connected clients to reconnect */ SV_Shutdown( "Server restarted\n", true ); } #ifndef DEDICATED_ONLY else { /* make sure the client is down */ CL_Drop(); SCR_BeginLoadingPlaque(); } #endif /* get any latched variable changes (maxclients, etc) */ Cvar_GetLatchedVars(); svs.initialized = true; if ( Cvar_VariableValue( "coop" ) && Cvar_VariableValue( "deathmatch" ) ) { Com_Printf( "Deathmatch and Coop both set, disabling Coop\n" ); Cvar_FullSet( "coop", "0", CVAR_SERVERINFO | CVAR_LATCH ); } /* dedicated servers can't be single player and are usually DM so unless they explicity set coop, force it to deathmatch */ if ( dedicated->value ) { if ( !Cvar_VariableValue( "coop" ) ) { Cvar_FullSet( "deathmatch", "1", CVAR_SERVERINFO | CVAR_LATCH ); } } /* init clients */ if ( Cvar_VariableValue( "deathmatch" ) ) { if ( maxclients->value <= 1 ) { Cvar_FullSet( "maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH ); } else if ( maxclients->value > MAX_CLIENTS ) { Cvar_FullSet( "maxclients", va( "%i", MAX_CLIENTS ), CVAR_SERVERINFO | CVAR_LATCH ); } } else if ( Cvar_VariableValue( "coop" ) ) { if ( ( maxclients->value <= 1 ) || ( maxclients->value > 4 ) ) { Cvar_FullSet( "maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH ); } } else /* non-deathmatch, non-coop is one player */ { Cvar_FullSet( "maxclients", "1", CVAR_SERVERINFO | CVAR_LATCH ); } svs.spawncount = randk(); svs.clients = Z_Malloc( sizeof ( client_t ) * maxclients->value ); svs.num_client_entities = maxclients->value * UPDATE_BACKUP * 64; svs.client_entities = Z_Malloc( sizeof ( entity_state_t ) * svs.num_client_entities ); /* init network stuff */ NET_Config( ( maxclients->value > 1 ) ); /* heartbeats will always be sent to the id master */ svs.last_heartbeat = -99999; /* send immediately */ Com_sprintf( idmaster, sizeof ( idmaster ), "192.246.40.37:%i", PORT_MASTER ); NET_StringToAdr( idmaster, &master_adr [ 0 ] ); /* init game */ SV_InitGameProgs(); for ( i = 0; i < maxclients->value; i++ ) { ent = EDICT_NUM( i + 1 ); ent->s.number = i + 1; svs.clients [ i ].edict = ent; memset( &svs.clients [ i ].lastcmd, 0, sizeof ( svs.clients [ i ].lastcmd ) ); } }
/* * go to a random point, but NOT the two * points closest to other players */ edict_t * SelectRandomDeathmatchSpawnPoint(void) { edict_t *spot, *spot1, *spot2; int count = 0; int selection; float range, range1, range2; spot = NULL; range1 = range2 = 99999; spot1 = spot2 = NULL; while ((spot = G_Find(spot, FOFS(classname), "info_player_deathmatch")) != NULL) { count++; range = PlayersRangeFromSpot(spot); if (range < range1) { range1 = range; spot1 = spot; } else if (range < range2) { range2 = range; spot2 = spot; } } if (!count) { return NULL; } if (count <= 2) { spot1 = spot2 = NULL; } else { if (spot1) { count--; } if (spot2) { count--; } } selection = randk() % count; spot = NULL; do { spot = G_Find(spot, FOFS(classname), "info_player_deathmatch"); if ((spot == spot1) || (spot == spot2)) { selection++; } } while (selection--); return spot; }
void rocket_touch(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) { vec3_t origin; int n; if (!ent || !other) { G_FreeEdict(ent); return; } if (other == ent->owner) { return; } if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict(ent); return; } if (ent->owner && 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) { if (plane) { T_Damage(other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, ent->dmg, 0, 0, MOD_ROCKET); } else { T_Damage(other, ent, ent->owner, ent->velocity, ent->s.origin, vec3_origin, 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 = randk() % 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 CL_AddPacketEntities(frame_t *frame) { entity_t ent = {0}; entity_state_t *s1; float autorotate; int i; int pnum; centity_t *cent; int autoanim; clientinfo_t *ci; unsigned int effects, renderfx; /* bonus items rotate at a fixed rate */ autorotate = anglemod(cl.time * 0.1f); /* brush models can auto animate their frames */ autoanim = 2 * cl.time / 1000; for (pnum = 0; pnum < frame->num_entities; pnum++) { s1 = &cl_parse_entities[(frame->parse_entities + pnum) & (MAX_PARSE_ENTITIES - 1)]; cent = &cl_entities[s1->number]; effects = s1->effects; renderfx = s1->renderfx; /* set frame */ if (effects & EF_ANIM01) { ent.frame = autoanim & 1; } else if (effects & EF_ANIM23) { ent.frame = 2 + (autoanim & 1); } else if (effects & EF_ANIM_ALL) { ent.frame = autoanim; } else if (effects & EF_ANIM_ALLFAST) { ent.frame = cl.time / 100; } else { ent.frame = s1->frame; } /* quad and pent can do different things on client */ if (effects & EF_PENT) { effects &= ~EF_PENT; effects |= EF_COLOR_SHELL; renderfx |= RF_SHELL_RED; } if (effects & EF_QUAD) { effects &= ~EF_QUAD; effects |= EF_COLOR_SHELL; renderfx |= RF_SHELL_BLUE; } if (effects & EF_DOUBLE) { effects &= ~EF_DOUBLE; effects |= EF_COLOR_SHELL; renderfx |= RF_SHELL_DOUBLE; } if (effects & EF_HALF_DAMAGE) { effects &= ~EF_HALF_DAMAGE; effects |= EF_COLOR_SHELL; renderfx |= RF_SHELL_HALF_DAM; } ent.oldframe = cent->prev.frame; ent.backlerp = 1.0f - cl.lerpfrac; if (renderfx & (RF_FRAMELERP | RF_BEAM)) { /* step origin discretely, because the frames do the animation properly */ VectorCopy(cent->current.origin, ent.origin); VectorCopy(cent->current.old_origin, ent.oldorigin); } else { /* interpolate origin */ for (i = 0; i < 3; i++) { ent.origin[i] = ent.oldorigin[i] = cent->prev.origin[i] + cl.lerpfrac * (cent->current.origin[i] - cent->prev.origin[i]); } } /* tweak the color of beams */ if (renderfx & RF_BEAM) { /* the four beam colors are encoded in 32 bits of skinnum (hack) */ ent.alpha = 0.30f; ent.skinnum = (s1->skinnum >> ((randk() % 4) * 8)) & 0xff; ent.model = NULL; } else { /* set skin */ if (s1->modelindex == 255)
void BossExplode ( edict_t *self ) { vec3_t org; q_int32_t n; if ( !self ) { return; } self->think = BossExplode; VectorCopy ( self->s.origin, org ); org[2] += 24 + ( randk() & 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 Weapon_Grenade(edict_t *ent) { if (!ent) { return; } 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->pers.inventory[ent->client->ammo_index]) { ent->client->ps.gunframe = 1; ent->client->weaponstate = WEAPON_FIRING; ent->client->grenade_time = 0; } else { if (level.time >= ent->pain_debounce_time) { PF_StartSound(ent, CHAN_VOICE, SV_SoundIndex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 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 (randk() & 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) { PF_StartSound(ent, CHAN_WEAPON, SV_SoundIndex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0); } if (ent->client->ps.gunframe == 11) { if (!ent->client->grenade_time) { ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2; ent->client->weapon_sound = SV_SoundIndex("weapons/hgrenc1b.wav"); } /* they waited too long, detonate it in their hand */ if (!ent->client->grenade_blew_up && (level.time >= ent->client->grenade_time)) { ent->client->weapon_sound = 0; weapon_grenade_fire(ent, true); ent->client->grenade_blew_up = true; } if (ent->client->buttons & BUTTON_ATTACK) { return; } if (ent->client->grenade_blew_up) { if (level.time >= ent->client->grenade_time) { ent->client->ps.gunframe = 15; ent->client->grenade_blew_up = false; } else { return; } } } if (ent->client->ps.gunframe == 12) { ent->client->weapon_sound = 0; weapon_grenade_fire(ent, false); } if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time)) { return; } ent->client->ps.gunframe++; if (ent->client->ps.gunframe == 16) { ent->client->grenade_time = 0; ent->client->weaponstate = WEAPON_READY; } } }
/* * A generic function to handle * the basics of weapon thinking */ 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 || !fire_frames || !fire) { return; } 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 (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; 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->pers.inventory[ent->client->ammo_index] >= ent->client->pers.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.time >= ent->pain_debounce_time) { PF_StartSound(ent, CHAN_VOICE, SV_SoundIndex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ent->pain_debounce_time = level.time + 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 (randk() & 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]) { fire(ent); break; } } if (!fire_frames[n]) { ent->client->ps.gunframe++; } if (ent->client->ps.gunframe == FRAME_IDLE_FIRST + 1) { ent->client->weaponstate = WEAPON_READY; } } }