diff --git a/config/sounds.cfg b/config/sounds.cfg index f8050098..5bad6c50 100755 --- a/config/sounds.cfg +++ b/config/sounds.cfg @@ -11,12 +11,10 @@ registersound "weapon/sniper" //S_SNIPER registersound "weapon/sniper_reload" //S_RSNIPER registersound "weapon/auto" //S_ASSULT registersound "weapon/auto_reload" //S_RASSULT -registersound "free/tick5" //S_GRENADE registersound "misc/pickup_ammo_clip" //S_ITEMAMMO registersound "misc/pickup_health" //S_ITEMHEALTH registersound "misc/pickup_armour" //S_ITEMARMOUR registersound "misc/tick9" //S_ITEMPUP -registersound "free/tick10" //S_ITEMSPAWN registersound "weapon/clip_empty" //S_NOAMMO registersound "misc/tick11" //S_PUPOUT 20 registersound "player/pain1" //S_PAIN1 @@ -27,10 +25,6 @@ registersound "player/pain5" //S_PAIN5 registersound "player/pain6" //S_PAIN6 registersound "player/die1" //S_DIE1 registersound "player/die2" //S_DIE2 -registersound "free/tick12" //S_SUICIDE -registersound "free/tick13" //S_FALL1 -registersound "free/tick14" //S_FALL2 -registersound "free/tick15" //S_FLAUNCH registersound "weapon/grenade_exp" //S_FEXPLODE registersound "player/splash1" //S_SPLASH1 registersound "player/splash2" //S_SPLASH2 diff --git a/packages/misc/base.png b/packages/misc/base.png new file mode 100644 index 00000000..0bafcdb7 Binary files /dev/null and b/packages/misc/base.png differ diff --git a/packages/misc/smoke.png b/packages/misc/smoke.png new file mode 100644 index 00000000..a57c234e Binary files /dev/null and b/packages/misc/smoke.png differ diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index 36f7d3ea..94f89fb0 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -57,6 +57,7 @@ void spawnstate(dynent *d) // reset player state not persistent acc d->gunwait = 0; d->attacking = false; d->lastaction = 0; + d->weaponchanging = false; if(d==player1) { gun_changed = true; @@ -85,7 +86,7 @@ dynent *newdynent() // create a new blank player or monster d->outsidemap = false; d->inwater = false; d->radius = 1.1f; - d->eyeheight = 4.25f; + d->eyeheight = 4.5f; //4.25f; d->aboveeye = 0.7f; d->frags = 0; d->flagscore = 0; // EDIT: AH @@ -105,8 +106,10 @@ dynent *newdynent() // create a new blank player or monster d->gunselect = GUN_PISTOL; d->onladder = false; d->isphysent = false; + d->inhandnade = NULL; d->skin = d->nextskin = 0; d->bIsBot = false; + d->weaponchanging = false; spawnstate(d); return d; }; @@ -203,14 +206,14 @@ void arenarespawn() }; -void checkakimbo(int time) +void checkakimbo() { - if(player1->gunselect==GUN_PISTOL && player1->akimbo && (player1->akimbomillis -= time)<0) + if(player1->gunselect==GUN_PISTOL && player1->akimbo && player1->akimbomillis && !player1->weaponchanging && player1->akimbomillis<=lastmillis) { player1->akimbomillis = 0; - player1->akimbo = false; + if(player1->gunselect==GUN_PISTOL) weaponswitch(GUN_PISTOL); + else player1->akimbo = false; playsoundc(S_PUPOUT); - //conoutf("quad damage is over"); }; }; @@ -276,7 +279,8 @@ void updateworld(int millis) // main game update loop curtime = millis - lastmillis; if(sleepwait && lastmillis>sleepwait) { execute(sleepcmd); sleepwait = 0; }; physicsframe(); - checkakimbo(curtime); + checkakimbo(); + checkweaponswitch(); //if(m_arena) arenarespawn(); arenarespawn(); moveprojectiles((float)curtime); @@ -621,7 +625,7 @@ void suicide() //else { addmsg(1, 4, SV_DAMAGE, d, dm, d->lifesequence); playsound(S_FALL1+rnd(5), &d->o); }; //particle_splash(3, 1000, 1000, player1->o); //edit out? demodamage(1000, player1->o); - playsound(S_SUICIDE, &player1->o); + //playsound(S_SUICIDE, &player1->o); // fixme sound }; COMMAND(suicide, ARG_NONE); diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index cbf1c470..9bea2e8b 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -220,9 +220,7 @@ void localservertoclient(uchar *buf, int len) // processes any updates from th e.y = getint(p)/DMF; e.z = getint(p)/DMF; if(gun==GUN_SHOTGUN) createrays(s, e); - int nademillis = 2000/100*getint(p); - if(nademillis<0 || nademillis>100) nademillis = 100; - shootv(gun, s, e, d, nademillis); + shootv(gun, s, e, d, getint(p)); break; }; diff --git a/source/src/cube.h b/source/src/cube.h index f5b0dff0..ba6dcfdf 100644 --- a/source/src/cube.h +++ b/source/src/cube.h @@ -46,7 +46,6 @@ enum // static entity types CARROT, // attr1 = tag, attr2 = type LADDER, CTF_FLAG, // attr1 = angle, attr2 = red/blue - SMOKESOURCE, // attr1 = type, attr2 = particles MAXENTTYPES }; @@ -206,17 +205,22 @@ struct dynent // players & monsters string name, team; int startheight; int shots; //keeps track of shots from auto weapons - bool reloading, hasarmour; + bool reloading, hasarmour, weaponchanging; + int nextweapon; // weapon we switch to int primary; //primary gun - int nextprimary; - int skin, nextskin; + int nextprimary; // primary after respawning + int skin, nextskin; // skin after respawning md3state animstate[3]; bool onladder; int gravity; bool isphysent; // hack + int thrownademillis; + struct physent *inhandnade; int akimbo; + int akimbolastaction[2]; + // Added by Rick CBot *pBot; // Only used if this is a bot, points to the bot class if we are the host, // for other clients its NULL @@ -264,6 +268,8 @@ enum { M_NONE = 0, M_SEARCH, M_HOME, M_ATTACKING, M_PAIN, M_SLEEP, M_AIMING, M_N #define CUBE_SERVINFO_PORT 28766 #define PROTOCOL_VERSION 121 // bump when protocol changes +#define WEAPONCHANGE_TIME 400 + // network messages codes, c2s, c2c, s2c enum { @@ -294,16 +300,14 @@ enum S_PISTOL, S_RPISTOL, S_SHOTGUN, S_RSHOTGUN, S_SUBGUN, S_RSUBGUN, - S_SNIPER, S_RSNIPER, //10 + S_SNIPER, S_RSNIPER, S_ASSULT, S_RASSULT, - S_GRENADE, S_ITEMAMMO, S_ITEMHEALTH, - S_ITEMARMOUR, S_ITEMPUP, S_ITEMSPAWN, - S_NOAMMO, S_PUPOUT, //20 + S_ITEMARMOUR, S_ITEMPUP, + S_NOAMMO, S_PUPOUT, S_PAIN1, S_PAIN2, S_PAIN3, S_PAIN4, S_PAIN5, S_PAIN6, - S_DIE1, S_DIE2, S_SUICIDE, - S_FALL1, S_FALL2, //31 - S_FLAUNCH, S_FEXPLODE, //33 + S_DIE1, S_DIE2, + S_FEXPLODE, S_SPLASH1, S_SPLASH2, S_GRUNT1, S_GRUNT2, S_RUMBLE, S_FLAGDROP, S_FLAGPICKUP, S_FLAGRETURN, S_FLAGSCORE, diff --git a/source/src/entities.cpp b/source/src/entities.cpp index c3a5a0cc..10a40fc0 100644 --- a/source/src/entities.cpp +++ b/source/src/entities.cpp @@ -50,24 +50,6 @@ void renderentities() rendermodel(mmi.name, 0, 7, 0, (float)mmi.rad, e.x, f.state==CTFF_INBASE ? (float)S(e.x, e.y)->floor : e.z, e.y, (float)((e.attr1+7)-(e.attr1+7)%15), 0, false, 1.0f, 120.0f, mmi.snap); }; } - else if(e.type==SMOKESOURCE) - { - - vec o, to; - o.x = e.x; - o.y = e.y; - o.z = e.z; - to = o; - to.z += 1000; - - //newparticle(o, to, 10000, 5); - static int lastsplash = lastmillis; - if(lastmillis - lastsplash > 100) - { - particle_splash(e.attr1, e.attr2, 1000, o); - lastsplash = lastmillis; - } - } else { if(OUTBORD(e.x, e.y)) continue; @@ -151,6 +133,9 @@ void realpickup(int n, dynent *d) break; case I_GRENADE: radditem(n, d->mag[6], 6); + player1->reloading = true; + player1->lastaction = lastmillis; + player1->thrownademillis = 0; break; case I_HEALTH: radditem(n, d->health, 7); @@ -160,11 +145,10 @@ void realpickup(int n, dynent *d) //d->hasarmour = true; break; case I_AKIMBO: - d->akimbo = true; - d->akimbomillis = 30000; + d->akimbomillis = lastmillis+30000; d->mag[GUN_PISTOL] = 16; radditem(n, d->ammo[1], 9); - weapon(G_SECONDARY); + weaponswitch(GUN_PISTOL); if(d==player1) conoutf("a lesser man would use a single pistol"); break; }; diff --git a/source/src/main.cpp b/source/src/main.cpp index 0c97d9c7..307a44e0 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -159,8 +159,8 @@ int main(int argc, char **argv) log("basetex"); int xs, ys; if(!installtex(2, path(newstring("packages/misc/newchars.png")), xs, ys) || - !installtex(3, path(newstring("packages/misc/martin/base.png")), xs, ys) || - !installtex(7, path(newstring("packages/misc/martin/smoke.png")), xs, ys) || + !installtex(3, path(newstring("packages/misc/base.png")), xs, ys) || + !installtex(7, path(newstring("packages/misc/smoke.png")), xs, ys) || !installtex(4, path(newstring("packages/misc/explosion.jpg")), xs, ys) || !installtex(5, path(newstring("packages/misc/items.png")), xs, ys) || !installtex(10, path(newstring("packages/misc/scope.png")), xs, ys) || diff --git a/source/src/physics.cpp b/source/src/physics.cpp index 5d8910a2..dd6b52fc 100644 --- a/source/src/physics.cpp +++ b/source/src/physics.cpp @@ -214,7 +214,8 @@ void physicsframe() // optimally schedule physics frames inside the gra void selfdamage(dynent *d, int dm) { if(d==player1) selfdamage(dm, -1, d); - else { addmsg(1, 4, SV_DAMAGE, d, dm, d->lifesequence); playsound(S_FALL1+rnd(5), &d->o); }; + else { addmsg(1, 4, SV_DAMAGE, d, dm, d->lifesequence); }; + //playsound(S_FALL1+rnd(5), &d->o); }; // fixme sound particle_splash(3, dm, 1000, d->o); //edit out? demodamage(dm, d->o); }; @@ -295,7 +296,7 @@ void moveplayer(dynent *pl, int moveres, bool local, int curtime) { selfdamage(damage,-1,pl); demodamage(damage, player1->o); - playsound(S_FALL1+rnd(2), &pl->o); + //playsound(S_FALL1+rnd(2), &pl->o); // fixme sound }; pl->startheight=pl->o.z; }; diff --git a/source/src/protos.h b/source/src/protos.h index 668a01dc..8c6e11af 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -239,7 +239,7 @@ extern ENetPacket *recvmap(int n); // weapon //extern void selectgun(int a = -1, int b = -1, int c =-1); extern void shoot(dynent *d, vec &to); -extern void shootv(int gun, vec &from, vec &to, dynent *d = 0, bool local = false, int nadesec = -1); +extern void shootv(int gun, vec &from, vec &to, dynent *d = 0, bool local = false, int nadepercent=0); extern void createrays(vec &from, vec &to); extern void moveprojectiles(float time); extern void projreset(); @@ -252,7 +252,8 @@ extern int kick_rot(int gun); extern int kick_back(int gun); extern bool gun_changed; extern bool akimboside; -extern int akimbolastaction[2]; +extern void checkweaponswitch(); +extern void weaponswitch(int gun); // Added by Rick extern char *botincrosshair(); extern bool intersect(dynent *d, vec &from, vec &to, vec *end = NULL); diff --git a/source/src/renderextras.cpp b/source/src/renderextras.cpp index adfe6948..e8e22d52 100644 --- a/source/src/renderextras.cpp +++ b/source/src/renderextras.cpp @@ -155,7 +155,7 @@ char *entnames[] = "clips", "ammobox","grenades", "health", "armour", "akimbo", "mapmodel", "trigger", - "ladder", "ctf-flag", "smokesource", "?", "?", + "ladder", "ctf-flag", "?", "?", "?", }; void renderents() // show sparkly thingies for map entities in edit mode diff --git a/source/src/rendermd3.cpp b/source/src/rendermd3.cpp index f1478da8..22d4b387 100644 --- a/source/src/rendermd3.cpp +++ b/source/src/rendermd3.cpp @@ -81,10 +81,11 @@ struct md3model bool loaded; vec scale; bool mirrored; + bool skipweaponmodel; void setanim(int anim); void setanimstate(md3state &as); bool link(md3model *link, char *tag); - bool load(char *path, bool mirror); + bool load(char *path, bool _mirrored); void render(); void draw(float x, float y, float z, float yaw, float pitch, float rad, vec &light); md3model(); @@ -99,6 +100,7 @@ md3model::md3model() // animstate = NULL; animstate = new md3state(); animstate->lastTime = lastmillis; + skipweaponmodel = false; }; md3model::~md3model() @@ -136,9 +138,9 @@ bool md3model::link(md3model *link, char *tag) return false; }; -bool md3model::load(char *path, bool mirror=false) +bool md3model::load(char *path, bool _mirrored=false) { - mirrored = mirror; + mirrored = _mirrored; if(!path) return false; FILE *f = fopen(path, "rb"); if(!f) return false; @@ -196,7 +198,6 @@ bool md3model::load(char *path, bool mirror=false) return true; }; -VAR(animdebug, 0, 0, 1); void md3model::render() { @@ -213,10 +214,8 @@ void md3model::render() float speed = 1000.0f / (float)info->fps; a->frm = (int) (time / speed); - //printf("no loop %i > %i\n", a->frm, info->start + info->num-1); if(!info->loop && a->frm >= info->num -1) { - if(animdebug) printf("no loop %i > %i\n", a->frm, info->start + info->num-1); a->frm = info->start + info->num-1; nextfrm = a->frm; } @@ -224,55 +223,24 @@ void md3model::render() { t = (time-a->frm*speed)/speed; a->frm = info->start+(a->frm % info->num); - //if(a->frm>=info->start+info->num-1) nextfrm = a->frm + 1; - //if(animdebug) printf("%i >= %i + %i", nextfrm, a->frm, info->num); if(nextfrm>=info->start+info->num) nextfrm=a->frm; }; - - //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 / (float) info->fps ); // t has a value from 0.0f to 1.0f - used for interpolation - - if(animdebug) printf("lm:%i lt:%i fps:%i\t(%i %i)\n", lastmillis, a->lastTime, info->fps, info->start, info->num); - - - /*if(t >= 1.0f) // jump to the next keyframe - { - a->frm++; - a->lastTime = lastmillis; - //t = 0.0f; - t = t % 1; - //printf("next keyframe\n"); - }; - if(a->frm >= info->end) - { - //printf("end\n"); - if(info->loop) - a->frm = info->start; - else - { - a->frm = info->end; - t = 0.0f; // stops the animation - }; - };*/ } else - { - if(animdebug) printf("overflow: curframe %i > maxframe %i\n", a->anim, animations.length()); - + { if(!a) a = new md3state(); a->frm = 0; nextfrm = a->frm + 1; } - if(animdebug) printf("interp. from frame %i to %i, %f percent done\n", a->frm, nextfrm, t*100.0f); - #define interpolate(p1,p2) ((p1) + t * ((p2) - (p1))) loopv(meshes) { md3mesh *mesh = &meshes[i]; + + if(skipweaponmodel && !strcmp(mesh->name, "weapon")) continue; glBindTexture(GL_TEXTURE_2D, FIRSTMD3 + mesh->tex); @@ -384,7 +352,6 @@ void md3animation(char *first, char *nums, char *loopings, char *fps) /* configu a.start = atoi(first); int n = atoi(nums); if(n<=0) n = 1; - //a.end = a.start + n - 1; a.num = n; (atoi(loopings) > 0) ? a.loop = true : a.loop = false; a.fps = atoi(fps); @@ -392,24 +359,37 @@ void md3animation(char *first, char *nums, char *loopings, char *fps) /* configu COMMAND(md3animation, ARG_5STR); +bool loadweapon(char *name, bool isakimbo=false) +{ + if(!name) return false; + sprintf(basedir, "packages/models/weapons/%s", name); + + md3model *mdl = new md3model(); + //models.add(mdl); + sprintf_sd(mdl_path)("%s/tris_high.md3", basedir); + sprintf_sd(cfg_path)("%s/default.skin", basedir); + sprintf_sd(modelcfg_path) ("%s/animations.cfg", basedir); + + if(!mdl->load(mdl_path, isakimbo)) + { + printf("could not load: %s\n", mdl_path); + delete mdl; + return false; + } + + models.add(mdl); + exec(cfg_path); + tmp_animations.setsize(0); + exec(modelcfg_path); + loopj(tmp_animations.length()) mdl->animations.add(tmp_animations[j]); + return true; +} + void loadweapons() { firstweapon = models.length(); - loopi(NUMGUNS+1) - { - bool akimbo = i==NUMGUNS; - sprintf(basedir, "packages/models/weapons/%s", akimbo ? hudgunnames[GUN_PISTOL] : 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); - sprintf_sd(modelcfg_path) ("%s/animations.cfg", basedir); - if(!mdl->load(mdl_path, akimbo)) printf("could not load: %s\n", mdl_path); - exec(cfg_path); - tmp_animations.setsize(0); - exec(modelcfg_path); - loopj(tmp_animations.length()) mdl->animations.add(tmp_animations[j]); - } + loopi(NUMGUNS) loadweapon(hudgunnames[i]); + loadweapon(hudgunnames[GUN_PISTOL], true); // akimbo }; VAR(swayspeeddiv, 1, 125, 1000); @@ -427,28 +407,32 @@ struct weaponmove float k_rot, kick; vec pos; int anim; - - weaponmove(vec base, int basetime) + + calcmove(vec base, int basetime) { bool akimbo = player1->akimbo && player1->gunselect==GUN_PISTOL; bool throwingnade = player1->gunselect==GUN_GRENADE && player1->thrownademillis; int timediff = throwingnade ? (lastmillis-player1->thrownademillis) : lastmillis-basetime; int animtime = attackdelay(player1->gunselect); int rtime = reloadtime(player1->gunselect); + bool attacking = player1->lastaction && player1->lastattackgun==player1->gunselect /*&& lastmillis-player1->lastactiono; anim = MDL_GUN_IDLE; - bool attacking = player1->lastaction && player1->lastattackgun==player1->gunselect /*&& lastmillis-player1->lastactionlastmillis) // akimbo gun queued for reloading + if(player1->weaponchanging) { - + anim = MDL_GUN_RELOAD; + float percent_done = (float)(timediff)*100.0f/(float) WEAPONCHANGE_TIME; + if(percent_done>=100 || percent_done<0) percent_done = 100; + k_rot = -(sin((float)(percent_done*2/100.0f*90.0f)*PI/180.0f)*90); } else if(player1->reloading) { anim = MDL_GUN_RELOAD; - float percent_done = (float)(timediff)*100.0f/rtime; - if(percent_done >= 100) percent_done = 100; + float percent_done = (float)(timediff)*100.0f/(float)rtime; + if(percent_done>=100 || percent_done<0) percent_done = 100; k_rot = -(sin((float)(percent_done*2/100.0f*90.0f)*PI/180.0f)*90); } else if(throwingnade && timediff>animtime-rtime/2 && timediffo.x; + int iy = (int)player1->o.y; + 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 = s->r/ll+of; + light.y = s->g/ll+of; + light.z = s->b/ll+of; + }; + + vdist(dist, unitv, player1->o, worldpos); + vdiv(unitv, dist); + + weaponmove wm; + wm.calcmove(unitv, lastaction); + weapon->setanim(wm.anim); + weapon->draw( wm.pos.x, wm.pos.z, wm.pos.y, player1->yaw + 90, player1->pitch+wm.k_rot, 1.0f, light); +}; + void rendermd3gun() { if(firstweapon >= 0) { - int ix = (int)player1->o.x; - int iy = (int)player1->o.y; - vec light = { 1.0f, 1.0f, 1.0f }; - - if(!OUTBORD(ix, iy)) + if(player1->akimbo && player1->gunselect==GUN_PISTOL) // akimbo { - sqr *s = S(ix,iy); - float ll = 256.0f; // 0.96f; - float of = 0.0f; // 0.1f; - light.x = s->r/ll+of; - light.y = s->g/ll+of; - light.z = s->b/ll+of; - }; - - vdist(dist, unitv, player1->o, worldpos); - vdiv(unitv, dist); - - md3model *weapon = models[firstweapon + player1->gunselect]; - md3model *akimbo = player1->akimbo && player1->gunselect==GUN_PISTOL ? models[firstweapon+NUMGUNS] : NULL; - - weaponmove *w1, *w2; - - if(akimbo) - { - w1 = new weaponmove(unitv, akimbolastaction[0]); - w2 = new weaponmove(unitv, akimbolastaction[1]); - akimbo->setanim(w2->anim); + rendergun(models[firstweapon+GUN_PISTOL], player1->akimbolastaction[0]); + rendergun(models[firstweapon+NUMGUNS], player1->akimbolastaction[1]); } - else w1 = new weaponmove(unitv, player1->lastaction); - - if(!w1) return; - weapon->setanim(w1->anim); - weapon->draw( w1->pos.x, w1->pos.z, w1->pos.y, player1->yaw + 90, player1->pitch+w1->k_rot, 1.0f, light); - - if(akimbo && w2) akimbo->draw( w2->pos.x, w2->pos.z, w2->pos.y, player1->yaw + 90, player1->pitch+w2->k_rot, 1.0f, light); + else + { + md3model *weapon = models[firstweapon + player1->gunselect]; + weapon->skipweaponmodel = (player1->gunselect==GUN_GRENADE && player1->mag[GUN_GRENADE]==0) ? true : false; + rendergun(weapon, player1->lastaction); + }; }; }; diff --git a/source/src/weapon.cpp b/source/src/weapon.cpp index 581b9db8..b7264a30 100644 --- a/source/src/weapon.cpp +++ b/source/src/weapon.cpp @@ -17,26 +17,50 @@ guninfo guns[NUMGUNS] = { S_SUBGUN, S_RSUBGUN, 1650, 80, 17, 0, 0, 70, 15, 30, 1, 2, "subgun" }, { S_SNIPER, S_RSNIPER, 1950, 1500, 72, 0, 0, 60, 50, 5, 4, 4, "sniper" }, { S_ASSULT, S_RASSULT, 2000, 130, 20, 0, 0, 20, 40, 20, 0, 2, "assult" }, //recoil was 44 - { S_GRENADE, S_NULL, 1000, 2500, 150, 20, 6, 1, 1, 1, 3, 1, "grenade" }, + { S_NULL, S_NULL, 1000, 2500, 150, 20, 6, 1, 1, 1, 3, 1, "grenade" }, }; - +int nadetimer = 2000; // detonate after $ms bool gun_changed = false; +void checkweaponswitch() +{ + if(!player1->weaponchanging) return; + int timeprogress = lastmillis-player1->lastaction; + + if(timeprogress>WEAPONCHANGE_TIME) player1->weaponchanging = false; + else if(timeprogress>WEAPONCHANGE_TIME/2) + { + gun_changed = true; + if( (!player1->akimbo && player1->akimbomillis && player1->nextweapon==GUN_PISTOL) || + (player1->akimbo && !player1->akimbomillis && player1->gunselect==GUN_PISTOL)) + player1->akimbo = !player1->akimbo; + player1->gunselect = player1->nextweapon; + }; +}; + +void weaponswitch(int gun) +{ + player1->weaponchanging = true; + player1->lastaction = player1->akimbolastaction[0] = player1->akimbolastaction[1] = lastmillis; + player1->nextweapon = gun; +} + void weapon(int gun) { if(scoped) togglescope(); gun %= G_NUM; if(gun<0) gun = G_NUM+gun; - gun_changed = true; switch(gun) { - case G_PRIMARY: player1->gunselect=player1->primary; break; - case G_SECONDARY: player1->gunselect=GUN_PISTOL; break; - case G_MELEE: player1->gunselect=GUN_KNIFE; break; - case G_GRENADE: player1->gunselect=GUN_GRENADE; break; + case G_PRIMARY: gun=player1->primary; break; + case G_SECONDARY: gun=GUN_PISTOL; break; + case G_MELEE: gun=GUN_KNIFE; break; + case G_GRENADE: gun=GUN_GRENADE; break; }; + + if(gun!=player1->gunselect) weaponswitch(gun); }; void shiftweapon(int i) @@ -67,48 +91,39 @@ COMMAND(altattack, ARG_NONE); void reload(dynent *d) { - if(!d) return; - + if(!d) return; if(scoped) togglescope(); - bool akimbo = d->gunselect==GUN_PISTOL && d->akimbo!=0; - if(d->gunselect==GUN_KNIFE || d->gunselect==GUN_GRENADE) return; - if(akimbo && d->mag[d->gunselect]>=(guns[d->gunselect].magsize * 2)) return; - else if(d->mag[d->gunselect]>=guns[d->gunselect].magsize && d->akimbo==0) return; - if(d->ammo[d->gunselect]<=0) return; - if(d->reloading) return; + if(d->gunselect==GUN_KNIFE || d->gunselect==GUN_GRENADE) return; + if(akimbo && d->mag[d->gunselect]>=(guns[d->gunselect].magsize * 2)) return; + else if(d->mag[d->gunselect]>=guns[d->gunselect].magsize && d->akimbo==0) return; + if(d->ammo[d->gunselect]<=0) return; + if(d->reloading) return; - d->reloading = true; - d->lastaction = lastmillis; - - if(akimbo) - { - akimbolastaction[akimboside?1:0] = lastmillis; - akimbolastaction[akimboside?0:1] = lastmillis;// + (reloadtime(GUN_PISTOL)/2); - }; + d->reloading = true; + d->lastaction = lastmillis; + d->akimbolastaction[0] = d->akimbolastaction[1] = lastmillis; - d->gunwait = guns[d->gunselect].reloadtime; - - //temp hack in drawhudgun() so no guns drawn while reloading, needs fixed + d->gunwait = guns[d->gunselect].reloadtime; + + int a = guns[d->gunselect].magsize - d->mag[d->gunselect]; + if(d->gunselect==GUN_PISTOL && d->akimbo!=0) + a = guns[d->gunselect].magsize * 2 - d->mag[d->gunselect]; + + if (a >= d->ammo[d->gunselect]) + { + d->mag[d->gunselect] += d->ammo[d->gunselect]; + d->ammo[d->gunselect] = 0; + } + else + { + d->mag[d->gunselect] += a; + d->ammo[d->gunselect] -= a; + } - int a = guns[d->gunselect].magsize - d->mag[d->gunselect]; - if(d->gunselect==GUN_PISTOL && d->akimbo!=0) - a = guns[d->gunselect].magsize * 2 - d->mag[d->gunselect]; - - if (a >= d->ammo[d->gunselect]) - { - d->mag[d->gunselect] += d->ammo[d->gunselect]; - d->ammo[d->gunselect] = 0; - } - else - { - d->mag[d->gunselect] += a; - d->ammo[d->gunselect] -= a; - } - - if(akimbo) playsoundc(S_RAKIMBO); - else playsoundc(guns[d->gunselect].reload); + if(akimbo) playsoundc(S_RAKIMBO); + else playsoundc(guns[d->gunselect].reload); }; void selfreload() { reload(player1); }; @@ -397,8 +412,6 @@ void moveprojectiles(float time) extern float rad(float x); -physent *curnade = NULL; - void throw_nade(dynent *d, vec &to, physent *p) { if(!p || !d) return; @@ -427,13 +440,14 @@ void throw_nade(dynent *d, vec &to, physent *p) vec &from = d->o; + d->thrownademillis = lastmillis; + d->inhandnade = NULL; + if(d==player1) { - int percent_done = (lastmillis-p->millis)*100/2000; + int percent_done = (lastmillis-p->millis)*100/nadetimer; if(percent_done < 0 || percent_done > 100) percent_done = 100; addmsg(1, 9, SV_SHOT, d->gunselect, (int)(from.x*DMF), (int)(from.y*DMF), (int)(from.z*DMF), (int)(to.x*DMF), (int)(to.y*DMF), (int)(to.z*DMF), percent_done); -// printf("grenade: %i\n", (lastmillis-curnade->millis)/100); - if(curnade) curnade = NULL; }; }; @@ -489,11 +503,9 @@ physent *new_nade(dynent *d, int millis = 0) p->millis = lastmillis; p->timetolife = 2000-millis; p->state = NADE_ACTIVATED; - if(d==player1) - { - curnade = p; - d->thrownademillis = 0; - }; + + d->inhandnade = p; + d->thrownademillis = 0; playsound(S_GRENADEPULL, &d->o); return p; }; @@ -514,7 +526,7 @@ void explode_nade(physent *i) newprojectile(i->o, i->o, 1, i->owner==player1, i->owner, GUN_GRENADE); }; -void shootv(int gun, vec &from, vec &to, dynent *d, bool local, int nademillis) // create visual effect from a shot +void shootv(int gun, vec &from, vec &to, dynent *d, bool local, int nadepercent) // create visual effect from a shot { playsound(guns[gun].sound, d==player1 ? NULL : &d->o); int pspeed = 25; @@ -541,6 +553,8 @@ void shootv(int gun, vec &from, vec &to, dynent *d, bool local, int nademillis) { if(d!=player1) { + int nademillis = nadetimer/100*nadepercent; + if(nademillis<0 || nademillis>100) nademillis = 100; physent *p = new_nade(d, nademillis); throw_nade(d, to, p); } @@ -619,24 +633,18 @@ void spreadandrecoil(vec & from, vec & to, dynent * d) if(d->pitch<80.0f) d->pitch += guns[d->gunselect].recoil*0.05f; }; -//VAR(grenadepulltime, 0, 100, 10000); + const int grenadepulltime = 650; bool akimboside = false; -int akimbolastaction[2] = {0,0}; - void shoot(dynent *d, vec &targ) { + if(d->weaponchanging) return; int attacktime = lastmillis-d->lastaction; - - if(!d->attacking && d->gunselect==GUN_GRENADE && curnade) // throw + if(d->gunselect==GUN_GRENADE && d->inhandnade && !d->attacking) // throw nade { - if(attacktime>grenadepulltime) - { - d->thrownademillis = lastmillis; - throw_nade(d, targ, curnade); - } + if(attacktime>grenadepulltime) throw_nade(d, targ, d->inhandnade); return; }; @@ -656,7 +664,7 @@ void shoot(dynent *d, vec &targ) if(d->gunselect==GUN_PISTOL && d->akimbo) { d->attacking = true; //make akimbo auto - akimbolastaction[akimboside?1:0] = lastmillis; + d->akimbolastaction[akimboside?1:0] = lastmillis; akimboside = !akimboside; } @@ -697,7 +705,7 @@ void shoot(dynent *d, vec &targ) if(d->gunselect==GUN_GRENADE) // activate { - if(!curnade) new_nade(d); + if(!d->inhandnade) new_nade(d); return; }