*** empty log message ***

git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@38 e016b1c5-ed68-44aa-a2f7-31cac88cffde
This commit is contained in:
driAn
2005-10-13 22:12:47 +00:00
parent 5d7a290652
commit f3f6bf158c
16 changed files with 498 additions and 456 deletions
+3 -2
View File
@@ -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)
+3 -3
View File
@@ -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;
};
+6 -4
View File
@@ -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);
};
};
+2
View File
@@ -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;
+3 -2
View File
@@ -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>;
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;
};
+41 -2
View File
@@ -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
+5 -5
View File
@@ -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();
};
+1 -1
View File
@@ -253,4 +253,4 @@ void item(int num)
};
COMMAND(item,ARG_1INT);
COMMAND(item,ARG_1INT);
+1 -1
View File
@@ -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--;
+8 -2
View File
@@ -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();
+10 -3
View File
@@ -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())
+9 -19
View File
@@ -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->lastaction<rtime)
{
drawhudmodel(7, 18, rtime/18.0f, player1->lastaction);
}
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);
+2 -2
View File
@@ -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<md2 *> *mdllookup = NULL;
vector<md2 *> mapmodels;
const int FIRSTMDL = 20;
const int FIRSTMDL = 40;
void delayedload(md2 *m)
{
+283 -356
View File
@@ -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<md3object> 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<md3mesh> meshes;
vector<md3animinfo> 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<md3model *> playermodels;
vector<md3model *> weaponmodels;
vector<md3model *> models;
vector<md3animinfo> 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);
};
};
+106 -42
View File
@@ -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()<FMOD_VERSION) fatal("old FMOD dll");
if(!FSOUND_Init(22050, 32, FSOUND_INIT_GLOBALFOCUS))
if(!FSOUND_Init(SOUNDFREQ, MAXCHAN, FSOUND_INIT_GLOBALFOCUS))
{
conoutf("sound init failed (FMOD): %d", FSOUND_GetError());
soundvol = 0;
nosound = true;
};
#endif
};
void music(char *name)
{
if(nosound) return;
stopsound();
if(soundvol && musicvol)
{
@@ -90,14 +97,14 @@ void music(char *name)
FMUSIC_PlaySong(mod);
FMUSIC_SetMasterVolume(mod, musicvol);
}
else if(stream = FSOUND_Stream_OpenFile(path(sn), FSOUND_LOOP_NORMAL, 0))
else if(stream = FSOUND_Stream_Open(path(sn), FSOUND_LOOP_NORMAL, 0, 0))
{
int chan = FSOUND_Stream_Play(FSOUND_FREE, stream);
if(chan>=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 && chan<MAXCHAN);
soundlocs[chan].loc = *loc;
soundlocs[chan].inuse = true;
};
void updatevol()
{
if(nosound) return;
loopi(MAXCHAN) if(soundlocs[i].inuse)
{
#ifdef USE_MIXER
if(Mix_Playing(i))
#else
if(FSOUND_IsPlaying(i))
#endif
updatechanvol(i, &soundlocs[i].loc);
else soundlocs[i].inuse = false;
};
};
COMMAND(updatevol, ARG_NONE);
void playsoundc(int n) { addmsg(0, 2, SV_SOUND, n); playsound(n); };
int soundsatonce = 0, lastsoundmillis = 0;
void playsound(int n, vec *loc)
{
if(nosound) return;
if(!soundvol) return;
if(lastmillis==lastsoundmillis) soundsatonce++; else soundsatonce = 1;
lastsoundmillis = lastmillis;
@@ -142,28 +210,24 @@ void playsound(int n, vec *loc)
#ifdef USE_MIXER
samples[n] = Mix_LoadWAV(path(buf));
#else
samples[n] = FSOUND_Sample_Load(n, path(buf), 0, 0);
samples[n] = FSOUND_Sample_Load(n, path(buf), FSOUND_LOOP_OFF, 0, 0);
#endif
if(!samples[n]) { conoutf("failed to load sample: %s", (int)&buf); return; };
if(!samples[n]) { conoutf("failed to load sample: %s", buf); return; };
};
int vol = soundvol;
if(loc)
{
vdist(d, v, *loc, player1->o);
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);
+15 -12
View File
@@ -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: