/* Copyright (C) 1997-2001 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // cl_event.c -- entity events: footsteps, etc. // moved from cl_fx.c #include "client.h" void CL_ItemRespawnParticles (vec3_t org); void CL_TeleportParticles (vec3_t org); #define MAX_TEX_SURF 2048 // was 256 struct texsurf_s { int step_id; char tex[32]; }; typedef struct texsurf_s texsurf_t; texsurf_t tex_surf[MAX_TEX_SURF]; int num_texsurfs; /* =============== ReadTextureSurfaceAssignments Reads in defintions for footsteps based on texture name. =============== */ #if 1 qboolean buf_gets (char *dest, int destsize, char **f) { char *old = *f; *f = strchr (old, '\n'); if (!*f) { // no more new lines *f = old + strlen(old); if (!strlen(*f)) return false; // end of file, nothing else to grab } (*f)++; // advance past EOL strncpy (dest, old, min(destsize-1, (int)(*f-old-1)) ); return true; } void ReadTextureSurfaceAssignments() { char filename[MAX_OSPATH]; char *footstep_data; char *parsedata; char line[80]; num_texsurfs = 0; Com_sprintf (filename, sizeof(filename), "texsurfs.txt"); FS_LoadFile (filename, (void **)&footstep_data); parsedata = footstep_data; if (!footstep_data) return; while (buf_gets(line, sizeof(line), &parsedata) && num_texsurfs < MAX_TEX_SURF) { sscanf(line,"%d %s",&tex_surf[num_texsurfs].step_id,tex_surf[num_texsurfs].tex); //Com_Printf("%d %s\n",tex_surf[num_texsurfs].step_id,tex_surf[num_texsurfs].tex); num_texsurfs++; } FS_FreeFile (footstep_data); } #else void ReadTextureSurfaceAssignments() { char filename[MAX_OSPATH]; FILE *f; char line[80]; num_texsurfs = 0; Com_sprintf (filename, sizeof(filename), "texsurfs.txt"); FS_FOpenFile (filename, &f); if (!f) return; while (fgets(line, sizeof(line), f) && num_texsurfs < MAX_TEX_SURF) { sscanf(line,"%d %s",&tex_surf[num_texsurfs].step_id,tex_surf[num_texsurfs].tex); //Com_Printf("%d %s\n",tex_surf[num_texsurfs].step_id,tex_surf[num_texsurfs].tex); num_texsurfs++; } fclose(f); } #endif /* =============== CL_FootSteps Plays appropriate footstep sound depending on surface flags of the ground surface. Since this is a replacement for plain Jane EV_FOOTSTEP, we already know the player is definitely on the ground when this is called. =============== */ void CL_FootSteps (entity_state_t *ent, qboolean loud) { trace_t tr; vec3_t end; int r; int surface; struct sfx_s *stepsound = NULL; float volume = 0.5; r = (rand()&3); VectorCopy(ent->origin,end); end[2] -= 64; tr = CL_PMSurfaceTrace (ent->number, ent->origin,NULL,NULL,end,MASK_SOLID | MASK_WATER); if (!tr.surface) return; surface = tr.surface->flags & SURF_STEPMASK; switch (surface) { case SURF_METAL: stepsound = clMedia.sfx_metal_footsteps[r]; break; case SURF_DIRT: stepsound = clMedia.sfx_dirt_footsteps[r]; break; case SURF_VENT: stepsound = clMedia.sfx_vent_footsteps[r]; break; case SURF_GRATE: stepsound = clMedia.sfx_grate_footsteps[r]; break; case SURF_TILE: stepsound = clMedia.sfx_tile_footsteps[r]; break; case SURF_GRASS: stepsound = clMedia.sfx_grass_footsteps[r]; break; case SURF_SNOW: stepsound = clMedia.sfx_snow_footsteps[r]; break; case SURF_CARPET: stepsound = clMedia.sfx_carpet_footsteps[r]; break; case SURF_FORCE: stepsound = clMedia.sfx_force_footsteps[r]; break; case SURF_GRAVEL: stepsound = clMedia.sfx_gravel_footsteps[r]; break; case SURF_ICE: stepsound = clMedia.sfx_ice_footsteps[r]; break; case SURF_SAND: stepsound = clMedia.sfx_sand_footsteps[r]; break; case SURF_WOOD: stepsound = clMedia.sfx_wood_footsteps[r]; break; case SURF_STANDARD: stepsound = clMedia.sfx_footsteps[r]; volume = 1.0; break; default: if (cl_footstep_override->value && num_texsurfs) { int i; for (i=0; iname,tex_surf[i].tex) && tex_surf[i].step_id > 0) { tr.surface->flags |= (SURF_METAL << (tex_surf[i].step_id - 1)); CL_FootSteps (ent, loud); // start over return; } } tr.surface->flags |= SURF_STANDARD; CL_FootSteps (ent, loud); // start over return; } if (loud) { if (volume == 1.0) S_StartSound (NULL, ent->number, CHAN_AUTO, stepsound, 1.0, ATTN_NORM, 0); else volume = 1.0; } S_StartSound (NULL, ent->number, CHAN_BODY, stepsound, volume, ATTN_NORM, 0); } //end Knightmare /* ============== CL_EntityEvent An entity has just been parsed that has an event value the female events are there for backwards compatability ============== */ void CL_EntityEvent (entity_state_t *ent) { switch (ent->event) { case EV_ITEM_RESPAWN: S_StartSound (NULL, ent->number, CHAN_WEAPON, S_RegisterSound("items/respawn1.wav"), 1, ATTN_IDLE, 0); CL_ItemRespawnParticles (ent->origin); break; case EV_PLAYER_TELEPORT: S_StartSound (NULL, ent->number, CHAN_WEAPON, S_RegisterSound("misc/tele1.wav"), 1, ATTN_IDLE, 0); CL_TeleportParticles (ent->origin); break; case EV_FOOTSTEP: if (cl_footsteps->value) //Knightmare- Lazarus footsteps //S_StartSound (NULL, ent->number, CHAN_BODY, clMedia.sfx_footsteps[rand()&3], 1, ATTN_NORM, 0); CL_FootSteps (ent, false); break; case EV_LOUDSTEP: if (cl_footsteps->value) CL_FootSteps (ent, true); break; //end Knightmare case EV_FALLSHORT: S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("player/land1.wav"), 1, ATTN_NORM, 0); break; case EV_FALL: S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("*fall2.wav"), 1, ATTN_NORM, 0); break; case EV_FALLFAR: S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("*fall1.wav"), 1, ATTN_NORM, 0); break; //Knightmare- more Lazarus sounds case EV_SLOSH: S_StartSound (NULL, ent->number, CHAN_BODY, clMedia.sfx_slosh[rand()&3], 0.5, ATTN_NORM, 0); break; case EV_WADE: S_StartSound (NULL, ent->number, CHAN_BODY, clMedia.sfx_wade[rand()&3], 0.5, ATTN_NORM, 0); break; case EV_WADE_MUD: S_StartSound (NULL, ent->number, CHAN_BODY, clMedia.sfx_mud_wade[rand()&1], 0.5, ATTN_NORM, 0); break; case EV_CLIMB_LADDER: S_StartSound (NULL, ent->number, CHAN_BODY, clMedia.sfx_ladder[rand()&3], 0.5, ATTN_NORM, 0); break; //end Knightmare } }