From f3f6bf158c986e5ec41b4eef24fc4cdfdfb05a5a Mon Sep 17 00:00:00 2001 From: driAn Date: Thu, 13 Oct 2005 22:12:47 +0000 Subject: [PATCH] *** empty log message *** git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@38 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/src/Makefile | 5 +- source/src/client.cpp | 6 +- source/src/clientextras.cpp | 10 +- source/src/clientgame.cpp | 2 + source/src/command.cpp | 5 +- source/src/cube.h | 43 ++- source/src/editing.cpp | 10 +- source/src/entities.cpp | 2 +- source/src/menus.cpp | 2 +- source/src/protos.h | 10 +- source/src/renderextras.cpp | 13 +- source/src/rendergl.cpp | 28 +- source/src/rendermd2.cpp | 4 +- source/src/rendermd3.cpp | 639 ++++++++++++++++-------------------- source/src/sound.cpp | 148 ++++++--- source/src/weapon.cpp | 27 +- 16 files changed, 498 insertions(+), 456 deletions(-) diff --git a/source/src/Makefile b/source/src/Makefile index 9dc47028..407c32bc 100644 --- a/source/src/Makefile +++ b/source/src/Makefile @@ -1,5 +1,5 @@ CXX=g++ -CXXOPTFLAGS=-Wall -O3 -fsigned-char -fomit-frame-pointer +CXXOPTFLAGS=-Wall -O3 -fsigned-char -fomit-frame-pointer -fpermissive CXXFLAGS=$(CXXOPTFLAGS) -I../enet/include `sdl-config --cflags` CLIENT_LIBS=-L../enet -lenet `sdl-config --libs` -lSDL_image -lSDL_mixer -lz -lGL -lGLU @@ -19,6 +19,7 @@ CLIENT_OBJS= \ renderextras.o \ rendergl.o \ rendermd2.o \ + rendermd3.o \ renderparticles.o \ rendertext.o \ rndmap.o \ @@ -58,7 +59,7 @@ standalone.o: $(CXX) $(CXXFLAGS) -DSTANDALONE -o standalone.o -c serverutil.cpp client: $(CLIENT_OBJS) - $(CXX) $(CXXFLAGS) -o ../../bin/ac_client $(CLIENT_OBJS) $(CLIENT_LIBS) + $(CXX) $(CXXFLAGS) -g -o ../../bin/ac_client $(CLIENT_OBJS) $(CLIENT_LIBS) server: $(SERVER_OBJS) $(CXX) $(CXXFLAGS) -o ../../bin/ac_server $(SERVER_OBJS) $(SERVER_LIBS) diff --git a/source/src/client.cpp b/source/src/client.cpp index b23016ca..e91eab97 100644 --- a/source/src/client.cpp +++ b/source/src/client.cpp @@ -25,7 +25,7 @@ bool allowedittoggle() return allow; }; -VARF(rate, 0, 0, 25000, if(clienthost) enet_host_bandwidth_limit (clienthost, rate, rate)); +VARF(rate, 0, 0, 25000, if(clienthost && (!rate || rate>1000)) enet_host_bandwidth_limit (clienthost, rate, rate)); void throttle(); @@ -51,11 +51,11 @@ void connects(char *servername) disconnect(1); // reset state addserver(servername); - conoutf("attempting to connect to %s", (int)servername); + conoutf("attempting to connect to %s", servername); ENetAddress address = { ENET_HOST_ANY, CUBE_SERVER_PORT }; if(enet_address_set_host(&address, servername) < 0) { - conoutf("could not resolve server %s", (int)servername); + conoutf("could not resolve server %s", servername); return; }; diff --git a/source/src/clientextras.cpp b/source/src/clientextras.cpp index ef13609d..dea334c6 100644 --- a/source/src/clientextras.cpp +++ b/source/src/clientextras.cpp @@ -35,7 +35,9 @@ void renderclient(dynent *d, bool team, char *mdlname, bool hellpig, float scale else if((!d->move && !d->strafe) || !d->moving) { n = 12; } else if(!d->onfloor && d->timeinair>100) { n = 18; } else { n = 14; speed = 1200/d->maxspeed*scale; if(hellpig) speed = 300/d->maxspeed; }; - if(hellpig) { n++; scale *= 32; mz -= 1.9f; }; + if(hellpig) { n++; scale *= 32; mz -= 1.9f; }; + n = 14; //fixme + basetime = -((int)d&0xFFF); rendermodel(mdlname, frame[n], range[n], 0, 1.5f, d->o.x, mz, d->o.y, d->yaw+90, d->pitch/2, team, scale, speed, 0, basetime); }; @@ -47,8 +49,8 @@ void renderclients() loopv(players) if((d = players[i]) && (!demoplayback || i!=democlientnum)) { - if (d->state==CS_DEAD) break; //cheap hack fix of - + if (d->state==CS_DEAD) break; //cheap hack fix of + if (!strcmp(d->team,"CT")) { renderclient(d, isteam(player1->team, d->team), "playermodels/counterterrorist", false,1.0f); @@ -58,7 +60,7 @@ void renderclients() renderclient(d, isteam(player1->team, d->team), "playermodels/terrorist", false, 1.0f); } - renderclient(d, isteam(player1->team, d->team), "playermodels/weapon", false, 1.0f); + renderclient(d, isteam(player1->team, d->team), "vwep/subgun", false, 1.0f); }; }; diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index d6bd4b87..90ed518b 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -520,6 +520,8 @@ dynent *getclient(int cn) // ensure valid entity return players[cn] ? players[cn] : (players[cn] = newdynent()); }; +void addc() { strcpy(getclient(1)->team, "CT"); getclient(1)->o = player1->o; strcpy(getclient(1)->name, "sucker"); } COMMAND(addc, ARG_NONE); // FIXME + void initclient() { clientmap[0] = 0; diff --git a/source/src/command.cpp b/source/src/command.cpp index 14021a48..2365f26e 100644 --- a/source/src/command.cpp +++ b/source/src/command.cpp @@ -14,6 +14,7 @@ struct ident void (*fun)(); // ID_VAR, ID_COMMAND int narg; // ID_VAR, ID_COMMAND char *action; // ID_ALIAS + bool persist; }; void itoa(char *s, int i) { sprintf_s(s)("%d", i); }; @@ -41,10 +42,10 @@ COMMAND(alias, ARG_2STR); // variable's and commands are registered through globals, see cube.h -int variable(char *name, int min, int cur, int max, int *storage, void (*fun)()) +int variable(char *name, int min, int cur, int max, int *storage, void (*fun)(), bool persist) { if(!idents) idents = new hashtable; - ident v = { ID_VAR, name, min, max, storage, fun, 0, 0 }; + ident v = { ID_VAR, name, min, max, storage, fun, 0, 0, persist }; idents->access(name, &v); return cur; }; diff --git a/source/src/cube.h b/source/src/cube.h index 6f0bcbfc..a369ec02 100644 --- a/source/src/cube.h +++ b/source/src/cube.h @@ -92,6 +92,42 @@ struct mapmodelinfo { int rad, h, zoff, snap; char *name; }; enum { GUN_KNIFE = 0, GUN_PISTOL, GUN_SHOTGUN, GUN_SUBGUN, GUN_SNIPER, GUN_ASSULT, GUN_GRENADE, NUMGUNS }; +struct md3state +{ + int anim; + int frm; + int lastTime; +}; + +enum // md3 animations +{ + BOTH_DEATH1 = 0, + BOTH_DEAD1, + BOTH_DEATH2, + BOTH_DEAD2, + BOTH_DEATH3, + BOTH_DEAD3, + TORSO_GESTURE, + TORSO_ATTACK, + TORSO_ATTACK2, + TORSO_DROP, + TORSO_RAISE, + TORSO_STAND, + TORSO_STAND2, + LEGS_WALKCR, + LEGS_WALK, + LEGS_RUN, + LEGS_BACK, + LEGS_SWIM, + LEGS_JUMP, + LEGS_LAND, + LEGS_JUMPB, + LEGS_LANDB, + LEGS_IDLE, + LEGS_IDLECR, + LEGS_TURN +}; + struct dynent // players & monsters { vec o, vel; // origin, velocity @@ -128,6 +164,7 @@ struct dynent // players & monsters bool reloading, hasarmour; int primary; //primary gun int nextprimary; + md3state animstate[3]; }; #define SAVEGAMEVERSION 6 // bump if dynent/netprotocol changes or any other savegame/demo data bumped from 5 @@ -265,8 +302,10 @@ enum // function signatures for script functions, see command.cpp // nasty macros for registering script functions, abuses globals to avoid excessive infrastructure #define COMMANDN(name, fun, nargs) static bool __dummy_##fun = addcommand(#name, (void (*)())fun, nargs) #define COMMAND(name, nargs) COMMANDN(name, name, nargs) -#define VAR(name, min, cur, max) int name = variable(#name, min, cur, max, &name, NULL) -#define VARF(name, min, cur, max, body) void var_##name(); static int name = variable(#name, min, cur, max, &name, var_##name); void var_##name() { body; } +#define VARP(name, min, cur, max) int name = variable(#name, min, cur, max, &name, NULL, true) +#define VAR(name, min, cur, max) int name = variable(#name, min, cur, max, &name, NULL, false) +#define VARF(name, min, cur, max, body) void var_##name(); static int name = variable(#name, min, cur, max, &name, var_##name, false); void var_##name() { body; } +#define VARFP(name, min, cur, max, body) void var_##name(); static int name = variable(#name, min, cur, max, &name, var_##name, true); void var_##name() { body; } #define ATOI(s) strtol(s, NULL, 0) // supports hexadecimal numbers diff --git a/source/src/editing.cpp b/source/src/editing.cpp index 4df636b7..2063d899 100644 --- a/source/src/editing.cpp +++ b/source/src/editing.cpp @@ -9,10 +9,10 @@ bool editmode = false; block sel = { - variable("selx", 0, 0, 4096, &sel.x, NULL), - variable("sely", 0, 0, 4096, &sel.y, NULL), - variable("selxs", 0, 0, 4096, &sel.xs, NULL), - variable("selys", 0, 0, 4096, &sel.ys, NULL), + variable("selx", 0, 0, 4096, &sel.x, NULL, false), + variable("sely", 0, 0, 4096, &sel.y, NULL, false), + variable("selxs", 0, 0, 4096, &sel.xs, NULL, false), + variable("selys", 0, 0, 4096, &sel.ys, NULL, false), }; int selh = 0; @@ -44,7 +44,7 @@ void toggleedit() else { resettagareas(); // clear trigger areas to allow them to be edited - player1->health = 100; + player1->health = 100; //put call to clear/restar gamemode projreset(); }; diff --git a/source/src/entities.cpp b/source/src/entities.cpp index a9ee111c..93fdfff3 100644 --- a/source/src/entities.cpp +++ b/source/src/entities.cpp @@ -253,4 +253,4 @@ void item(int num) }; -COMMAND(item,ARG_1INT); \ No newline at end of file +COMMAND(item,ARG_1INT); diff --git a/source/src/menus.cpp b/source/src/menus.cpp index df8beb85..0a61a7de 100644 --- a/source/src/menus.cpp +++ b/source/src/menus.cpp @@ -121,7 +121,7 @@ bool menukey(int code, bool isdown) { menuset(-1); if(!menustack.empty()) menuset(menustack.pop()); - execute("musicvol 0; music $menu_music"); + execute("musicvol 1"); return true; } else if(code==SDLK_UP || code==-4) menusel--; diff --git a/source/src/protos.h b/source/src/protos.h index 382fa6cb..4000ae42 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -1,7 +1,7 @@ // protos for ALL external functions in cube... // command -extern int variable(char *name, int min, int cur, int max, int *storage, void (*fun)()); +extern int variable(char *name, int min, int cur, int max, int *storage, void (*fun)(), bool persist); extern void setvar(char *name, int i); extern int getvar(char *name); extern bool identexists(char *name); @@ -42,6 +42,7 @@ extern void mipstats(int a, int b, int c); extern void vertf(float v1, float v2, float v3, sqr *ls, float t1, float t2); extern void addstrip(int tex, int start, int n); extern int lookuptexture(int tex, int &xs, int &ys); +extern char *hudgunnames[]; // rendercubes extern void resetcubes(); @@ -196,6 +197,9 @@ extern void cleansound(); extern void rendermodel(char *mdl, int frame, int range, int tex, float rad, float x, float y, float z, float yaw, float pitch, bool teammate, float scale, float speed, int snap = 0, int basetime = 0); extern mapmodelinfo &getmminfo(int i); +// rendermd3 +extern void rendermd3gun(); + // server extern void initserver(bool dedicated, bool listen, int uprate, char *sdesc, char *ip, char *master, char *passwd); extern void cleanupserver(); @@ -222,8 +226,10 @@ extern void shootv(int gun, vec &from, vec &to, dynent *d = 0, bool local = fals extern void createrays(vec &from, vec &to); extern void moveprojectiles(float time); extern void projreset(); -extern char *playerincrosshair(); +extern dynent *playerincrosshair(); extern int reloadtime(int gun); +extern int kick_rot(int gun); +extern int kick_back(int gun); // entities extern void renderents(); diff --git a/source/src/renderextras.cpp b/source/src/renderextras.cpp index 073873cd..bbc4dc84 100644 --- a/source/src/renderextras.cpp +++ b/source/src/renderextras.cpp @@ -265,7 +265,8 @@ VAR(hidestats, 0, 0, 1); VAR(crosshairfx, 0, 1, 1); void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater) -{ +{ + readmatrices(); if(editmode) { @@ -301,10 +302,16 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat glEnable(GL_TEXTURE_2D); char *command = getcurcommand(); - char *player = playerincrosshair(); + dynent *player = playerincrosshair(); if(command) draw_textf("> %s_", 20, 1570, 2, (int)command); else if(closeent[0]) draw_text(closeent, 20, 1570, 2); - else if(player) draw_text(player, 20, 1570, 2); + else if(player) + { + string plinfo; + if(isteam(player->team, player1->team)) sprintf_s(plinfo)("%s (health:%i armour:%i)", player->name, player->health, player->armour); + else sprintf_s(plinfo)("%s", player->name); + draw_text(plinfo, 20, 1570, 2); + }; renderscores(); if(!rendermenu()) diff --git a/source/src/rendergl.cpp b/source/src/rendergl.cpp index a5a7786f..3feb25c8 100644 --- a/source/src/rendergl.cpp +++ b/source/src/rendergl.cpp @@ -262,40 +262,30 @@ VAR(fogcolour, 0, 0x8099B3, 0xFFFFFF); VAR(hudgun,0,1,1); -char *hudgunnames[] = { "hudguns/knife", "hudguns/pistol", "hudguns/shotgun", "hudguns/subgun", "hudguns/sniper", "hudguns/assult", "hudguns/grenade" }; +char *hudgunnames[] = { "knife", "semipistol", "shotgun", "subgun", "sniper", "auto", "grenade" }; void drawhudmodel(int start, int end, float speed, int base) { - rendermodel(hudgunnames[player1->gunselect], start, end, 0, 1.0f, player1->o.x, player1->o.z, player1->o.y, player1->yaw+90, player1->pitch, false, 1.0f, speed, 0, base); + sprintf_sd(mdl)("hudguns/%s", hudgunnames[player1->gunselect]); + rendermodel(mdl, start, end, 0, 1.0f, player1->o.x, player1->o.z, player1->o.y, player1->yaw+90, player1->pitch, false, 1.0f, speed, 0, base); }; -void drawhudgun(float fovy, float aspect, int farplane) +void drawhudgun(int w, int h, float aspect, int farplane) { if(!hudgun) return; - if(player1->reloading) return; //temp hack by argh - glEnable(GL_CULL_FACE); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - gluPerspective(fovy, aspect, 0.3f, farplane); + gluPerspective((float)100.0f*h/w, aspect, 0.3f, farplane); // fov fixed at 100° glMatrixMode(GL_MODELVIEW); - - //glClear(GL_DEPTH_BUFFER_BIT); - int rtime = reloadtime(player1->gunselect); - if(player1->lastattackgun==player1->gunselect && lastmillis-player1->lastactionlastaction); - } - else - { - drawhudmodel(6, 1, 100, 0); - }; + + rendermd3gun(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - gluPerspective(fovy, aspect, 0.15f, farplane); + gluPerspective((float)fov*h/w, aspect, 0.15f, farplane); glMatrixMode(GL_MODELVIEW); glDisable(GL_CULL_FACE); @@ -378,7 +368,7 @@ void gl_drawframe(int w, int h, float changelod, float curfps) glDisable(GL_CULL_FACE); - drawhudgun(fovy, aspect, farplane); + drawhudgun(w, h, aspect, farplane); overbright(1); int nquads = renderwater(hf); diff --git a/source/src/rendermd2.cpp b/source/src/rendermd2.cpp index 5e067889..09e5ada0 100644 --- a/source/src/rendermd2.cpp +++ b/source/src/rendermd2.cpp @@ -124,7 +124,7 @@ void md2::scale(int frame, float scale, int sn) }; void md2::render(vec &light, int frame, int range, float x, float y, float z, float yaw, float pitch, float sc, float speed, int snap, int basetime) -{ +{ loopi(range) if(!mverts[frame+i]) scale(frame+i, sc, snap); glPushMatrix (); @@ -193,7 +193,7 @@ void md2::render(vec &light, int frame, int range, float x, float y, float z, fl hashtable *mdllookup = NULL; vector mapmodels; -const int FIRSTMDL = 20; +const int FIRSTMDL = 40; void delayedload(md2 *m) { diff --git a/source/src/rendermd3.cpp b/source/src/rendermd3.cpp index 61631ab0..74dafc0f 100644 --- a/source/src/rendermd3.cpp +++ b/source/src/rendermd3.cpp @@ -1,81 +1,34 @@ +// code for loading, linking and rendering md3 models +// See http://www.draekko.org/documentation/md3format.html for informations about the md3 format + #include "cube.h" -// loading and rendering code for the MD3 model format -// parts of the code are from gamedev.net - const int FIRSTMD3 = 20; -int nummodels = 0; -int numskins = 0; +enum { MDL_LOWER = 0, MDL_UPPER, MDL_HEAD }; -struct vec2 +#define MD3_DEFAULT_SCALE 0.08f + +struct vec2 { float x, y; }; -struct md3header -{ - char fileID[4]; - int version; - char filename[68]; - int numFrames, numTags, numMeshes; - int maxSkins; - int headersize; - int tagStart, tagEnd; - int filesize; -}; - -struct md3meshinfo -{ - char meshId[4]; - char name[68]; - int numMeshFrames, numSkins, numVertices, numTriangles; - int triStart; - int headersize; - int uvStart; - int vertexStart; - int meshSize; -}; - struct md3tag { - char name[64]; - vec pos; - float rotation[3][3]; + char name[64]; + float pos[3]; + float rotation[3][3]; }; -struct md3bone +struct md3vertex { - float mins[3], maxs[3]; - float position[3]; - float scale; - char creator[16]; + signed short vertex[3]; + uchar normal[2]; }; struct md3triangle { - signed short vertex[3]; - unsigned char normal[2]; -}; - -struct md3face -{ - int vertexindices[3]; -}; - -struct md3texcoord -{ - float texturecoord[2]; -}; - -struct md3skin -{ - char name[68]; -}; - -struct md3tface -{ - int vertindex[3]; - int coordindex[3]; + int vertexindices[3]; }; struct md3animinfo @@ -86,33 +39,47 @@ struct md3animinfo int fps; }; -struct md3object +struct md3header { - int numVerts, numFaces, numTexVertex; - int tex; - char name[255]; - vec *verts; - vec *normals; - vec2 *texVerts; - md3tface *faces; - int numTags;//EDIT: AH + char id[4]; + int version; + char name[64]; + int flags; + int numframes, numtags, nummeshes, numskins; + int ofs_frames, ofs_tags, ofs_meshes, ofs_eof; // offsets }; -struct md3model +struct md3meshheader { - vector objects; + char id[4]; + char name[64]; + int flags; + int numframes, numshaders, numvertices, numtriangles; + int ofs_triangles, ofs_shaders, ofs_uv, ofs_vertices, meshsize; // offsets +}; + +struct md3mesh +{ + char name[64]; + md3triangle *triangles; + vec *vertices; + vec2 *uv; + int numtriangles, numvertices; // numvertices == numUV + int tex; +}; + +struct md3model +{ + vector meshes; vector animations; - md3model **links; - md3tag *tags; - int numTags; -/* int curAnim, curFrame, nextFrame; - int lastTime; */ md3state *animstate; + md3model **links; + md3tag *tags; + int numframes, numtags; bool loaded; - int modelnum; - float scale; - bool load(char *mdlpath); - void link(md3model *link, char *tag); + vec scale; + bool link(md3model *link, char *tag); + bool load(char *path); void render(); void draw(float x, float y, float z, float yaw, float pitch, float rad); md3model(); @@ -122,229 +89,169 @@ struct md3model md3model::md3model() { loaded = false; - scale = 0.08f; + scale.x = scale.y = scale.z = MD3_DEFAULT_SCALE; + animstate = NULL; }; md3model::~md3model() { - loopv(objects){ - if(objects[i].verts) delete [] objects[i].verts; - if(objects[i].normals) delete [] objects[i].normals; - if(objects[i].texVerts) delete [] objects[i].texVerts; - if(objects[i].faces) delete [] objects[i].faces; + loopv(meshes){ + if(meshes[i].vertices) delete [] meshes[i].vertices; + if(meshes[i].triangles) delete [] meshes[i].triangles; + if(meshes[i].uv) delete [] meshes[i].uv; }; if(links) free(links); if(tags) delete [] tags; }; -bool md3model::load(char *mdlpath) +bool md3model::link(md3model *link, char *tag) { - loaded = false; - if(!mdlpath) return false; + loopi(numtags) + if(strcmp(tags[i].name, tag) == 0) + { + links[i] = link; + return true; + }; + return false; +}; - FILE *f = fopen(mdlpath, "rb"); - if(!f) { conoutf("could not load md3 model: %s", (int)mdlpath); return false; }; +bool md3model::load(char *path) +{ + if(!path) return false; + FILE *f = fopen(path, "rb"); + if(!f) fatal("could not load md3 model: %s", path); md3header header; - fread(&header, 1, sizeof(header), f); - char *id = header.fileID; - if(id[0] != 'I' || id[1] != 'D' || id[2] != 'P' || header.version != 15) { // check the header - conoutf("wrong header in md3 model: %s", (int)mdlpath); - return false; - }; + fread(&header, sizeof(md3header), 1, f); + if(header.id[0] != 'I' || header.id[1] != 'D' || header.id[2] != 'P' || header.id[3] != '3' || header.version != 15) // header check + fatal("corruped header in md3 model: %s", path); - md3bone *bones = new md3bone[header.numFrames]; // read bones - fread(bones, sizeof(md3bone), header.numFrames, f); - delete [] bones; + tags = new md3tag[header.numframes * header.numtags]; + fseek(f, header.ofs_tags, SEEK_SET); + fread(tags, sizeof(md3tag), header.numframes * header.numtags, f); + numframes = header.numframes; + numtags = header.numtags; - tags = new md3tag[header.numFrames * header.numTags]; // read tags - fread(tags, sizeof(md3tag), header.numFrames * header.numTags, f); - numTags = header.numTags; + links = (md3model **) malloc(sizeof(md3model) * header.numtags); + loopi(header.numtags) links[i] = NULL; + + int mesh_offset = ftell(f); - links = (md3model **) malloc(sizeof(md3model) * header.numTags); // alloc mem for the links - loopi(header.numTags) links[i] = NULL; - - long meshOffset = ftell(f); - md3meshinfo meshHeader; - - loopj(header.numMeshes) // go through all sub objects - { - fseek(f, meshOffset, SEEK_SET); // read header - fread(&meshHeader, sizeof(md3meshinfo), 1, f); - - md3skin *skins = new md3skin[meshHeader.numSkins]; - md3texcoord *texcoords = new md3texcoord[meshHeader.numVertices]; - md3face *triangles = new md3face[meshHeader.numTriangles]; - md3triangle *vertices = new md3triangle[meshHeader.numVertices * meshHeader.numMeshFrames]; + loopi(header.nummeshes) + { + md3mesh mesh; + md3meshheader mheader; + fseek(f, mesh_offset, SEEK_SET); + fread(&mheader, sizeof(md3meshheader), 1, f); + strn0cpy(mesh.name, mheader.name, 64); + + mesh.triangles = new md3triangle[mheader.numtriangles]; + fseek(f, mesh_offset + mheader.ofs_triangles, SEEK_SET); + fread(mesh.triangles, sizeof(md3triangle), mheader.numtriangles, f); // read the triangles + mesh.numtriangles = mheader.numtriangles; + + mesh.uv = new vec2[mheader.numvertices]; + fseek(f, mesh_offset + mheader.ofs_uv , SEEK_SET); + fread(mesh.uv, sizeof(vec2), mheader.numvertices, f); // read the UV data - fread(skins, sizeof(md3skin), meshHeader.numSkins, f); // read skin information - - fseek(f, meshOffset + meshHeader.triStart, SEEK_SET); // read triangles/face data - fread(triangles, sizeof(md3face), meshHeader.numTriangles, f); - - fseek(f, meshOffset + meshHeader.uvStart, SEEK_SET); // read UV data - fread(texcoords, sizeof(md3texcoord), meshHeader.numVertices, f); - - fseek(f, meshOffset + meshHeader.vertexStart, SEEK_SET); // read vertex/face index information - fread(vertices, sizeof(md3triangle), meshHeader.numMeshFrames * meshHeader.numVertices, f); - - md3object currentMesh = {0}; - strcpy(currentMesh.name, meshHeader.name); - - currentMesh.numVerts = meshHeader.numVertices; - currentMesh.numTexVertex = meshHeader.numVertices; - currentMesh.numFaces = meshHeader.numTriangles; - - currentMesh.verts = new vec[currentMesh.numVerts * meshHeader.numMeshFrames]; - currentMesh.texVerts = new vec2 [currentMesh.numVerts]; - currentMesh.faces = new md3tface [currentMesh.numFaces]; - - loopi(currentMesh.numVerts * meshHeader.numMeshFrames) + md3vertex *vertices = new md3vertex[mheader.numframes * mheader.numvertices]; + fseek(f, mesh_offset + mheader.ofs_vertices, SEEK_SET); + fread(vertices, sizeof(md3vertex), mheader.numframes * mheader.numvertices, f); // read the vertices + mesh.vertices = new vec[mheader.numframes * mheader.numvertices]; // transform to our own structure + loopj(mheader.numframes * mheader.numvertices) { - currentMesh.verts[i].x = vertices[i].vertex[0] / 64.0f; - currentMesh.verts[i].y = vertices[i].vertex[1] / 64.0f; - currentMesh.verts[i].z = vertices[i].vertex[2] / 64.0f; - } - - loopi(currentMesh.numTexVertex) - { - currentMesh.texVerts[i].x = texcoords[i].texturecoord[0]; - currentMesh.texVerts[i].y = -texcoords[i].texturecoord[1]; - } - - loopi(currentMesh.numFaces) - { - currentMesh.faces[i].vertindex[0] = triangles[i].vertexindices[0]; - currentMesh.faces[i].vertindex[1] = triangles[i].vertexindices[1]; - currentMesh.faces[i].vertindex[2] = triangles[i].vertexindices[2]; - - currentMesh.faces[i].coordindex[0] = triangles[i].vertexindices[0]; - currentMesh.faces[i].coordindex[1] = triangles[i].vertexindices[1]; - currentMesh.faces[i].coordindex[2] = triangles[i].vertexindices[2]; - } + mesh.vertices[j].x = vertices[j].vertex[0] / 64.0f; + mesh.vertices[j].y = vertices[j].vertex[1] / 64.0f; + mesh.vertices[j].z = vertices[j].vertex[2] / 64.0f; + }; + mesh.numvertices = mheader.numvertices; - objects.add(currentMesh); - - delete [] skins; - delete [] texcoords; - delete [] triangles; - delete [] vertices; - meshOffset += meshHeader.meshSize; + meshes.add(mesh); + mesh_offset += mheader.meshsize; + delete [] vertices; }; loaded = true; return true; }; -void md3model::link(md3model *link, char *tag) -{ - loopi(numTags) - if(strcmp(tags[i].name, tag) == 0) - { - links[i] = link; - return; - }; -}; +VAR(anim, 0, 0, 100); void md3model::render() { - int startfrm = 0; - int endfrm = 1; + if(!loaded || meshes.length() <= 0) return; float t = 0.0f; - + int nextfrm; md3state *a = animstate; - md3animinfo *anim = NULL; - if(animations.length()) + if(a && animations.length() > a->anim) { - anim = &animations[a->anim]; - /*if(a->frm < anim->start || a->frm > anim->end) + md3animinfo *info = &animations[a->anim]; + if(a->frm < info->start || a->frm > info->end) // we switched to a new animation, jump to the start + a->frm = info->start; + t = (float) (lastmillis - a->lastTime) / (1000.0f / info->fps); // t has a value from 0.0f to 1.0f - used for interpolation + if(t >= 1.0f) // jump to the next keyframe { - a->frm = anim->start; - a->lastTime = lastmillis; - };*/ - startfrm = anim->start; - endfrm = anim->end; - } - - int nextfrm = (a->frm + 1) % endfrm; - if(nextfrm == 0) - { - if(anim && anim->loop) nextfrm = startfrm; - else + a->frm++; a->lastTime = lastmillis; - }; - int elapsedtime = 0; - - if(animations.length()) - { - elapsedtime = lastmillis - a->lastTime; - t = (float) elapsedtime / (1000 / anim->fps); - if(t >= 1.0f) - { t = 0.0f; - a->frm = nextfrm; - a->lastTime = lastmillis; }; - }; - - loopv(objects) + if(a->frm >= info->end) + { + if(info->loop) + a->frm = info->start; + else + { + a->frm = info->end; + t = 0.0f; // stops the animation + }; + }; + } + else { - md3object *obj = &objects[i]; - - int currentIndex = a->frm * obj->numVerts; - int nextIndex = nextfrm * obj->numVerts; + a = new md3state(); + a->frm = 0; + } + a->frm = anim; //fixme + nextfrm = a->frm + 1; - glBindTexture(GL_TEXTURE_2D, obj->tex + FIRSTMD3); + #define interpolate(p1,p2) ((p1) + t * ((p2) - (p1))) + + loopv(meshes) + { + md3mesh *mesh = &meshes[i]; + + glBindTexture(GL_TEXTURE_2D, FIRSTMD3 + mesh->tex); glBegin(GL_TRIANGLES); - loopj(obj->numFaces) + loopj(mesh->numtriangles) // triangles { - loop(whichVertex, 3) + loopk(3) // vertices { - int index = obj->faces[j].vertindex[whichVertex]; - - if(obj->texVerts) - glTexCoord2f(obj->texVerts[index].x, -obj->texVerts[index].y); - - vec point1 = obj->verts[ currentIndex + index ]; - vec point2 = obj->verts[ nextIndex + index]; - - glVertex3f(point1.x + t * (point2.x - point1.x), - point1.y + t * (point2.y - point1.y), - point1.z + t * (point2.z - point1.z)); - } - } + int index = mesh->triangles[j].vertexindices[k]; + vec *point1 = &mesh->vertices[index + a->frm * mesh->numvertices]; + vec *point2 = &mesh->vertices[index + nextfrm * mesh->numvertices]; + + if(mesh->uv) + glTexCoord2f(mesh->uv[index].x, mesh->uv[index].y); + + glVertex3f( interpolate(point1->x, point2->x), + interpolate(point1->y, point2->y), + interpolate(point1->z, point2->z)); + }; + }; glEnd(); - } - - #define ip(r, c,n) (r) = (c) + t * ((n) - (c)) - #define ip_vec(c,n) ip(c.x,c.x,n.x); ip(c.y,c.y,n.y); ip(c.z,c.z,n.z); - loopi(numTags) + }; + + loopi(numtags) // render the linked models - interpolate rotation and position of the 'link-tags' { md3model *link = links[i]; if(!link) continue; - vec pos = tags[a->frm * numTags + i].pos; - vec nextpos = tags[nextfrm * numTags + i].pos; - ip_vec(pos, nextpos); - float rot[3][3]; - loop(j, 3) loop(k, 3) ip(rot[j][k], tags[a->frm * numTags + i].rotation[j][k], tags[nextfrm * numTags + i].rotation[j][k]); - GLfloat matrix[16]; - matrix[0] = rot[0][0]; - matrix[1] = rot[0][1]; - matrix[2] = rot[0][2]; - matrix[3] = 0; - matrix[4] = rot[1][0]; - matrix[5] = rot[1][1]; - matrix[6] = rot[1][2]; - matrix[7] = 0; - matrix[8] = rot[2][0]; - matrix[9] = rot[2][1]; - matrix[10]= rot[2][2]; - matrix[11]= 0; - matrix[12] = pos.x; - matrix[13] = pos.y; - matrix[14] = pos.z; - matrix[15] = 1; + GLfloat matrix[16] = {0}; // fixme: un-obfuscate it! + loopj(3) matrix[j] = interpolate(tags[a->frm * numtags + i].rotation[0][j], tags[nextfrm * numtags + i].rotation[0][j]); // rotation + loopj(3) matrix[4 + j] = interpolate(tags[a->frm * numtags + i].rotation[1][j], tags[nextfrm * numtags + i].rotation[1][j]); + loopj(3) matrix[8 + j] = interpolate(tags[a->frm * numtags + i].rotation[2][j], tags[nextfrm * numtags + i].rotation[2][j]); + loopj(3) matrix[12 + j] = interpolate(tags[a->frm * numtags + i].pos[j] , tags[nextfrm * numtags + i].pos[j]); // position + matrix[15] = 1.0f; glPushMatrix(); glMultMatrixf(matrix); link->render(); @@ -354,33 +261,17 @@ void md3model::render() void md3model::draw(float x, float y, float z, float yaw, float pitch, float rad) { - if(!loaded || objects.length() <= 0) return; - //if(isoccluded(player1->o.x, player1->o.y, x-rad, z-rad, rad*2)) return; - glPushMatrix(); - int ix = (int)x; - int iy = (int)z; - vec light = { 1.0f, 1.0f, 1.0f }; - if(!OUTBORD(ix, iy)) - { - sqr *s = S(ix,iy); - float ll = 256.0f; // 0.96f; - float of = 0.0f; // 0.1f; - light.x = 0.75f * s->r/ll+of; - light.y = 0.75f * s->g/ll+of; - light.z = 0.75f * s->b/ll+of; - }; - glColor3fv((float *)&light); - - glTranslatef(x, y, z); // avoid models above ground + glTranslatef(x, y, z); glRotatef(yaw+180, 0, -1, 0); glRotatef(pitch, 0, 0, 1); + + glRotatef(-90, 0, 1, 0); glRotatef(-90, 1, 0, 0); - glScalef( scale, scale, scale); - glTranslatef( 0.0f, 0.0f, 24.0f ); + glScalef( scale.x, scale.y, scale.z); render(); @@ -400,23 +291,24 @@ void md3setanim(dynent *d, int anim) d->animstate[MDL_LOWER].anim = anim - 7; }; -vector playermodels; -vector weaponmodels; +vector models; vector tmp_animations; +int firstweapon = -1; +int numskins = 0; char basedir[_MAXDEFSTR]; // necessary for relative path's void md3skin(char *objname, char *skin) // called by the {lower|upper|head}.cfg (originally .skin in Q3A) { - md3model *mdl = playermodels.last(); - loopv(mdl->objects) + md3model *mdl = models.last(); + loopv(mdl->meshes) { - md3object *obj = &mdl->objects[i]; - if(strcmp(obj->name, objname) == 0) + md3mesh *mesh = &mdl->meshes[i]; + if(strcmp(mesh->name, objname) == 0) { int xs, ys; sprintf_sd(path)("%s/%s", basedir, skin); // 'skin' is a relative url installtex(FIRSTMD3 + numskins, path, xs, ys); - obj->tex = numskins; + mesh->tex = numskins; numskins++; }; }; @@ -428,86 +320,39 @@ void md3animation(char *first, char *nums, char *loopings, char *fps) /* configu { md3animinfo &a = tmp_animations.add(); a.start = atoi(first); - a.end = a.start + atoi(nums); + a.end = a.start + atoi(nums) - 1; (atoi(loopings) > 0) ? a.loop = true : a.loop = false; a.fps = atoi(fps); }; COMMAND(md3animation, ARG_5STR); -/* -void rendermd3(char *mdl, float x, float y, float z, float yaw, float pitch, float rad) -{ - if(playermodels.length()) playermodels[MDL_LOWER]->draw(x, y, z, yaw, pitch, rad); -};*/ - -VAR(anim, 0, 0, 1000); - -void rendermd3player(dynent *d) -{ - if(playermodels.length() >= 3 && d->mdl[MDL_LOWER] == 0) - { - loopi(3) playermodels[d->mdl[i]]->animstate = &d->animstate[i]; // get d's current - - md3setanim(d, anim); - - int n; - float mz = d->o.z-d->eyeheight+1.55f; - /*if(d->state==CS_DEAD) - { - - md3setanim(d, BOTH_DEATH1 + rnd(2) * 2); - //mdl = (((int)d>>6)&1)+1; - //mz = d->o.z-d->eyeheight+0.2f; - //scale = 1.2f; - } - else if(d->state==CS_EDITING) { md3setanim(d, TORSO_STAND); } - else if(d->state==CS_LAGGED) { md3setanim(d, LEGS_IDLE); md3setanim(d, TORSO_GESTURE); } - else if(d->monsterstate==M_ATTACKING) { n = 8; } - else if(d->monsterstate==M_PAIN) { n = 10; } - else if((!d->move && !d->strafe) || !d->moving) { md3setanim(d, LEGS_IDLE); md3setanim(d, TORSO_STAND); } - else if(!d->onfloor && d->timeinair>100) { md3setanim(d, LEGS_JUMP ); } - else { n = 14; }; */ - - playermodels[d->mdl[MDL_LOWER]]->draw(d->o.x, mz, d->o.y, d->yaw+90, d->pitch, d->radius); - }; -}; - -void testrender(float x, float y, float z, float yaw, float pitch, float radius) -{ - if(playermodels.length()) - { - playermodels[0]->draw(x, z, y, yaw+90, pitch, radius); - }; -}; - -md3model *loadmd3(char *path) // loads a single md3 model and the skins for its objects (cfg file) -{ - md3model *mdl = new md3model(); - playermodels.add(mdl); - sprintf_sd(mdl_path)("%s.md3", path); - sprintf_sd(cfg_path)("%s.cfg", path); - playermodels.last()->load(mdl_path); - exec(cfg_path); - return playermodels.last(); -}; - -char pl_objects[3][6] = {"lower", "upper", "head"}; - void loadplayermdl(char *model) { + char pl_objects[3][6] = {"lower", "upper", "head"}; tmp_animations.setsize(0); - sprintf(basedir, "packages/models/playermodels/%s", model); + sprintf(basedir, "packages/models/players/%s", model); md3model *mdls[3]; - loopi(3) // load lower,upper and head objects + loopi(3) // load lower,upper and head models { sprintf_sd(path)("%s/%s", basedir, pl_objects[i]); - mdls[i] = loadmd3(path); + mdls[i] = new md3model(); + models.add(mdls[i]); + sprintf_sd(mdl_path)("%s.md3", path); + sprintf_sd(cfg_path)("%s.cfg", path); + mdls[i]->load(mdl_path); + exec(cfg_path); }; - //mdls[MDL_LOWER]->link(mdls[MDL_UPPER], "tag_torso"); - //mdls[MDL_UPPER]->link(mdls[MDL_HEAD], "tag_head"); - sprintf_sd(modelcfg)("%s/model.cfg", basedir); + mdls[MDL_LOWER]->link(mdls[MDL_UPPER], "tag_torso"); + mdls[MDL_UPPER]->link(mdls[MDL_HEAD], "tag_head"); + sprintf_sd(modelcfg)("%s/animation.cfg", basedir); exec(modelcfg); // load animations to tmp_animation + int skip_gap = tmp_animations[LEGS_WALKCR].start - tmp_animations[TORSO_GESTURE].start; + for(int i = LEGS_WALKCR; i < tmp_animations.length(); i++) // the upper and lower mdl frames are independent + { + tmp_animations[i].start -= skip_gap; + tmp_animations[i].end -= skip_gap; + }; loopv(tmp_animations) // assign the loaded animations to the lower,upper or head model { md3animinfo &anim = tmp_animations[i]; @@ -525,8 +370,90 @@ void loadplayermdl(char *model) COMMAND(loadplayermdl, ARG_1STR); -void test1() +enum {MDL_GUN_IDLE, MDL_GUN_RELOAD, NUM_MDL_GUN}; +/*md3animinfo weaponsanim[] = { {0, 8, 8, 25}, + {8, 15, 0, 25}, + {16,25, 0, 25} };*/ + +md3animinfo weaponsanim[] = { {0, 8, 8, 25}, + {8, 25, 0, 25} }; + +void loadweapons() { - md3model test; - test.load("packages/models/playermodels/lara/lower.md3"); -}; COMMAND(test1, ARG_NONE); + firstweapon = models.length(); + loopi(NUMGUNS) + { + sprintf(basedir, "packages/models/weapons/%s", hudgunnames[i]); + md3model *mdl = new md3model(); + models.add(mdl); + sprintf_sd(mdl_path)("%s/tris_high.md3", basedir); + sprintf_sd(cfg_path)("%s/default.skin", basedir); + mdl->load(mdl_path); + exec(cfg_path); + loopj(NUM_MDL_GUN) mdl->animations.add(weaponsanim[j]); + } +}; + +COMMAND(loadweapons, ARG_NONE); + +void rendermd3gun() +{ + if(firstweapon >= 0) + { + md3model *weapon = models[firstweapon + player1->gunselect]; + int rtime = reloadtime(player1->gunselect); + if(player1->reloading) + { + weapon->animstate = new md3state(); + weapon->animstate->anim = MDL_GUN_RELOAD; + } + else + { + weapon->animstate = new md3state(); + weapon->animstate->anim = MDL_GUN_IDLE; + }; + float kick = 0.0f; + if(player1->gunselect==player1->lastattackgun) + { + int percent_done = (lastmillis-player1->lastaction)*100/reloadtime(player1->gunselect); + if(percent_done > 100) percent_done = 100.0; + // f(x) = -sin(x-1.5)^3 + kick = -sin(pow((1.5f/100*percent_done)-1.5f,3)); + }; + vdist(dist, unitv, player1->o, worldpos); + vdiv(unitv, dist); + float k_rot = kick_rot(player1->gunselect)*kick; + float k_back = kick_back(player1->gunselect)*kick/10; + weapon->draw(player1->o.x-unitv.x*k_back, player1->o.z-unitv.z*k_back, player1->o.y-unitv.y*k_back, player1->yaw + 90, player1->pitch+k_rot, 1.0f); + }; +}; + +void rendermd3player(dynent *d) +{ + if(models.length() >= 3) + { + loopi(3) models[i]->animstate = &d->animstate[i]; + + float mz = d->o.z-d->eyeheight+1.55f; + + if(d->state == CS_DEAD) { md3setanim(d, BOTH_DEATH1); } + else if(d->state == CS_EDITING) { md3setanim(d, LEGS_IDLECR); md3setanim(d, TORSO_GESTURE); } + else if(d->state == CS_LAGGED) { md3setanim(d, LEGS_IDLECR); md3setanim(d, TORSO_DROP); } + else + { + if(!d->onfloor && d->timeinair>100) { md3setanim(d, LEGS_JUMP); } + else if((!d->move && !d->strafe)) { md3setanim(d, LEGS_IDLE); } + else { md3setanim(d, LEGS_RUN); } + + if(d->attacking) { md3setanim(d, TORSO_ATTACK2); } + else { md3setanim(d, TORSO_STAND); } + }; + if(d->gunselect >= models.length()) + models[MDL_UPPER]->link(NULL, "tag_weapon"); // no weapon model + else + models[MDL_UPPER]->link(models[d->gunselect], "tag_weapon"); // show current weapon + + models[MDL_LOWER]->draw(d->o.x, mz, d->o.y, d->yaw+90, d->pitch/2, d->radius); + }; +}; + diff --git a/source/src/sound.cpp b/source/src/sound.cpp index c4ac8b7f..04a52e0d 100644 --- a/source/src/sound.cpp +++ b/source/src/sound.cpp @@ -2,27 +2,39 @@ #include "cube.h" -#ifndef WIN32 +//#ifndef WIN32 // NOTE: fmod not being supported for the moment as it does not allow stereo pan/vol updating during playback #define USE_MIXER -#endif +//#endif -VAR(soundvol, 0, 255, 255); -VAR(musicvol, 0, 128, 255); +bool nosound = false; -#ifdef USE_MIXER +#define MAXCHAN 32 +#define SOUNDFREQ 22050 + +struct soundloc { vec loc; bool inuse; } soundlocs[MAXCHAN]; + +#ifdef USE_MIXER #include "SDL_mixer.h" #define MAXVOL MIX_MAX_VOLUME Mix_Music *mod = NULL; - void *stream = NULL; // TODO + void *stream = NULL; #else #include "fmod.h" #define MAXVOL 255 FMUSIC_MODULE *mod = NULL; FSOUND_STREAM *stream = NULL; -#endif +#endif + +#ifdef USE_MIXER +VARFP(musicvol, 0, 128, 255, Mix_VolumeMusic((musicvol*MAXVOL)/255)); +#else +VARP(musicvol, 0, 128, 255); +#endif +VARP(soundvol, 0, 255, 255); void stopsound() { + if(nosound) return; if(mod) { #ifdef USE_MIXER @@ -42,36 +54,31 @@ void stopsound() }; }; -void cleansound() -{ - stopsound(); - #ifdef USE_MIXER - Mix_CloseAudio(); - #else - FSOUND_Close(); - #endif -}; +VAR(soundbufferlen, 128, 1024, 4096); void initsound() { + memset(soundlocs, 0, sizeof(soundloc)*MAXCHAN); #ifdef USE_MIXER - if(Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2, 512)<0) + if(Mix_OpenAudio(SOUNDFREQ, MIX_DEFAULT_FORMAT, 2, soundbufferlen)<0) { - conoutf("sound init failed (SDL_mixer): %s", (int) Mix_GetError()); - soundvol = 0; - }; + conoutf("sound init failed (SDL_mixer): %s", (size_t)Mix_GetError()); + nosound = true; + }; + Mix_AllocateChannels(MAXCHAN); #else if(FSOUND_GetVersion()=0) { FSOUND_SetVolume(chan, (musicvol*MAXVOL)/255); FSOUND_SetPaused(chan, false); }; } else { - conoutf("could not play music: %s", (int)&sn); + conoutf("could not play music: %s", sn); }; #endif }; @@ -123,12 +130,73 @@ int registersound(char *name) COMMAND(registersound, ARG_1EST); +void cleansound() +{ + if(nosound) return; + stopsound(); + #ifdef USE_MIXER + Mix_CloseAudio(); + #else + FSOUND_Close(); + #endif +}; + +VAR(stereo, 0, 1, 1); + +void updatechanvol(int chan, vec *loc) +{ + int vol = soundvol, pan = 255/2; + if(loc) + { + vdist(dist, v, *loc, player1->o); + vol -= (int)(dist*3*soundvol/255); // simple mono distance attenuation + if(stereo && (v.x != 0 || v.y != 0)) + { + float yaw = -atan2(v.x, v.y) - player1->yaw*(PI / 180.0f); // relative angle of sound along X-Y axis + pan = int(255.9f*(0.5*sin(yaw)+0.5f)); // range is from 0 (left) to 255 (right) + }; + }; + vol = (vol*MAXVOL)/255; + #ifdef USE_MIXER + Mix_Volume(chan, vol); + Mix_SetPanning(chan, 255-pan, pan); + #else + FSOUND_SetVolume(chan, vol); + FSOUND_SetPan(chan, pan); + #endif +}; + +void newsoundloc(int chan, vec *loc) +{ + assert(chan>=0 && chano); - vol -= (int)(d*3*soundvol/255); // simple mono distance attenuation - } - if(vol<=0) return; - - #ifdef USE_MIXER - int chan = Mix_PlayChannel(-1, samples[n], 0); - if(chan>=0) Mix_Volume(chan, (vol*MAXVOL)/255); - #else - int chan = FSOUND_PlaySoundEx(FSOUND_FREE, samples[n], NULL, true); - if(chan>=0) { FSOUND_SetVolume(chan, (vol*MAXVOL)/255); FSOUND_SetPaused(chan, false); }; - #endif + + #ifdef USE_MIXER + int chan = Mix_PlayChannel(-1, samples[n], 0); + #else + int chan = FSOUND_PlaySoundEx(FSOUND_FREE, samples[n], NULL, true); + #endif + if(chan<0) return; + if(loc) newsoundloc(chan, loc); + updatechanvol(chan, loc); + #ifndef USE_MIXER + FSOUND_SetPaused(chan, false); + #endif }; void sound(int n) { playsound(n, NULL); }; COMMAND(sound, ARG_1INT); - diff --git a/source/src/weapon.cpp b/source/src/weapon.cpp index 67e5b4e3..ca6349d8 100644 --- a/source/src/weapon.cpp +++ b/source/src/weapon.cpp @@ -2,7 +2,7 @@ #include "cube.h" -struct guninfo { short sound, reload, reloadtime, attackdelay, damage, projspeed, part, spread, recoil, magsize; char *name; }; +struct guninfo { short sound, reload, reloadtime, attackdelay, damage, projspeed, part, spread, recoil, magsize, mdl_kick_rot, mdl_kick_back; char *name; }; const int SGRAYS = 20; //down from 20 (defualt) const float SGSPREAD = 2; @@ -11,19 +11,19 @@ vec sg[SGRAYS]; //change the particales guninfo guns[NUMGUNS] = { - { S_KNIFE, S_NULL, 0, 250, 50, 0, 0, 1, 1, 1, "knife" }, + { S_KNIFE, S_NULL, 0, 250, 50, 0, 0, 1, 1, 1, 0, 0, "knife" }, - { S_PISTOL, S_RPISTOL, 1400, 170, 20, 0, 0, 20, 10, 8, "pistol" }, // *SGRAYS + { S_PISTOL, S_RPISTOL, 1400, 170, 20, 0, 0, 20, 10, 8, 6, 5, "pistol" }, // *SGRAYS - { S_SHOTGUN, S_RSHOTGUN, 2400, 1100, 6, 0, 0, 1, 35, 7, "shotgun" }, //reload time is for 1 shell from 7 too powerful to 6 + { S_SHOTGUN, S_RSHOTGUN, 2400, 1100, 6, 0, 0, 1, 35, 7, 10, 10, "shotgun" }, //reload time is for 1 shell from 7 too powerful to 6 - { S_SUBGUN, S_RSUBGUN, 1650, 90, 14, 0, 0, 45, 15, 30, "subgun" }, + { S_SUBGUN, S_RSUBGUN, 1650, 90, 14, 0, 0, 45, 15, 30, 3, 2, "subgun" }, - { S_SNIPER, S_RSNIPER, 1950, 1500, 72, 0, 0, 60, 50, 5, "sniper" }, + { S_SNIPER, S_RSNIPER, 1950, 1500, 72, 0, 0, 60, 50, 5, 3, 2, "sniper" }, - { S_ASSULT, S_RASSULT, 2000, 130, 33, 0, 0, 90, 40, 20, "assult" }, //recoil was 44 + { S_ASSULT, S_RASSULT, 2000, 130, 33, 0, 0, 90, 40, 20, 4, 2, "assult" }, //recoil was 44 - { S_GRENADE, S_NULL, 0, 2000, 40, 30, 6, 1, 1, 1, "grenade" }, + { S_GRENADE, S_NULL, 0, 2000, 40, 30, 6, 1, 1, 1, 3, 1, "grenade" }, }; //weapon selection @@ -120,7 +120,9 @@ void reload() COMMAND(reload,ARG_NONE); -int reloadtime(int gun) { return guns[gun].attackdelay; }; +int reloadtime(int gun) { return guns[gun].attackdelay; }; +int kick_rot(int gun) { return guns[gun].mdl_kick_rot; }; +int kick_back(int gun) { return guns[gun].mdl_kick_back; }; void createrays(vec &from, vec &to) // create random spread of rays for the shotgun @@ -165,14 +167,14 @@ bool intersect(dynent *d, vec &from, vec &to) // if lineseg hits entity boundi && p->z >= d->o.z-d->eyeheight; }; -char *playerincrosshair() +dynent *playerincrosshair() { if(demoplayback) return NULL; loopv(players) { dynent *o = players[i]; if(!o) continue; - if(intersect(o, player1->o, worldpos)) return o->name; + if(intersect(o, player1->o, worldpos)) return o; }; return NULL; }; @@ -322,7 +324,8 @@ void shootv(int gun, vec &from, vec &to, dynent *d, bool local) // create vi case GUN_GRENADE: pspeed = guns[gun].projspeed; - newprojectile(from, to, (float)pspeed, local, d, gun); + newprojectile(from, to, (float)pspeed, local, d, gun); + conoutf("NADE"); break; case GUN_SNIPER: