fun changes
This commit is contained in:
@@ -176,6 +176,12 @@ menuitemslider "Gravity Multiplier: " 50 500 "$matchgravity" 10 [ matchset match
|
||||
menuitemslider "Friction Multiplier: " 10 500 "$matchfriction" 10 [ matchset matchfriction $arg1 ]
|
||||
menuitem "" -1
|
||||
menuitemcheckbox "Enable Assists: " "$matchassist" [ matchset matchassist $arg1 ]
|
||||
menuitemcheckbox "Reload cancel on switch: " "$matchreloadcancel" [ matchset matchreloadcancel $arg1 ]
|
||||
menuitemcheckbox "Knife+jump speed boost: " "$matchknifeboost" [ matchset matchknifeboost $arg1 ]
|
||||
menuitemcheckbox "Medkit pickup item: " "$matchmedkit" [ matchset matchmedkit $arg1 ]
|
||||
menuitemcheckbox "Slow backwards walk (70%): " "$matchbackwards" [ matchset matchbackwards $arg1 ]
|
||||
menuitemcheckbox "Ceiling bump speed boost: " "$matchheadboost" [ matchset matchheadboost $arg1 ]
|
||||
menuitemcheckbox "Source-style physics (bhop/air strafe): " "$matchsourcephysics" [ matchset matchsourcephysics $arg1 ]
|
||||
menuitemcheckbox "Explosive Deaths: " "$matchdeathexplosion" [ matchset matchdeathexplosion $arg1 ]
|
||||
menuitemslider " Blast Radius %: " 10 300 "$matchdeathradius" 10 [ matchset matchdeathradius $arg1 ]
|
||||
menuitemslider " Blast Power %: " 10 500 "$matchdeathpower" 10 [ matchset matchdeathpower $arg1 ]
|
||||
|
||||
@@ -141,6 +141,7 @@ menuitemcheckbox [ Damage screen flash ] "$damagescreen" [
|
||||
menuitemslider [ Damage maxroll: ] 0 (getvarrange max maxrolleffect) "$maxrolleffect" 1 [ maxrolleffect $arg1 ]
|
||||
menuitemcheckbox [ Team score counters ] "(= $hideteamscorehud 0)" [ hideteamscorehud (= $arg1 0) ]
|
||||
menuitemcheckbox [ KTF flag direction indicator ] "(! $hidektfindicator)" [ hidektfindicator (! $arg1) ]
|
||||
menuitemcheckbox [ Grenade cook bar ] "$showgrenadebar" [ showgrenadebar $arg1 ]
|
||||
menuitemcheckbox [ Radar ] "(= $hideradar 0)" [ hideradar (= $arg1 0) ]
|
||||
menuitemslider [ Radar zoom: ] 5 500 [ $radarheight ] 5 [ radarheight $arg1 ] 1
|
||||
menuitemslider [ Votes: ] 0 2 "$hidevote" ["Always show" "Show until you vote" "Never show"] [ hidevote $arg1 ] 1
|
||||
@@ -327,6 +328,7 @@ menuitemkeyinput [Special action: ] altaction
|
||||
menuitemkeyinput [Knife attack: ] key_knifeattack
|
||||
menuitemkeyinput [Quick grenade throw: ] quicknadethrow
|
||||
menuitemkeyinput [Reload: ] reload
|
||||
menuitemkeyinput [Use medkit: ] usemedkit
|
||||
menuitemkeyinput [Weapon menu: ] key_showmenuweapons
|
||||
menuitemkeyinput [Primary weapon: ] primary
|
||||
menuitemkeyinput [Secondary weapon: ] secondary
|
||||
|
||||
@@ -24,6 +24,7 @@ alias key_voteno [ if $votepending [ && (vote 2) (echo you voted no) ] ]
|
||||
alias key_teamchat [ saycommand % ]
|
||||
alias key_commandline [ saycommand / ]
|
||||
alias key_prevweapon [ weapon (prevweapon) ]
|
||||
alias key_usemedkit [ usemedkit ]
|
||||
alias key_pause [ if $connected togglepause [ paused (! $paused) ]]
|
||||
|
||||
alias editkey_editmeta2 [ editmeta2down = 1 ; onrelease [ editmeta2down = 0 ] ]
|
||||
@@ -155,7 +156,7 @@ editbind F editkey_cubes_solid
|
||||
specbind F speckey_demo_togglespeed
|
||||
bind G quicknadethrow
|
||||
editbind G editkey_cubes_space
|
||||
bind H []
|
||||
bind H key_usemedkit
|
||||
editbind H editkey_cubes_hf_floor
|
||||
bind I []
|
||||
editbind I editkey_cubes_hf_ceiling
|
||||
|
||||
@@ -1030,6 +1030,10 @@ void parsemessages(int cn, playerent *d, ucharbuf &p, bool demo = false)
|
||||
case SV_ARENAWIN:
|
||||
{
|
||||
int acn = getint(p);
|
||||
static int lastarenawin = 0;
|
||||
// a single round end can arrive several times in one burst: announce it once
|
||||
if(lastarenawin && lastmillis - lastarenawin < 1500) break;
|
||||
lastarenawin = lastmillis;
|
||||
playerent *alive = getclient(acn);
|
||||
conoutf("the round is over! next round in 5 seconds...");
|
||||
if(m_botmode && acn==-2) hudoutf("the bots have won the round!");
|
||||
|
||||
+26
-4
@@ -91,7 +91,7 @@ extern int matchdeathradius, matchdeathpower;
|
||||
// the values, sends them to every client when they change and to everybody who joins (SV_MATCHSETTINGS).
|
||||
// Offline/bot games have no server, so there you simply set them yourself. Defined in server.cpp (which is part of the client too).
|
||||
struct matchsettingdef { const char *name; int *var; int min, def, max; };
|
||||
#define NUMMATCHSETTINGS 14
|
||||
#define NUMMATCHSETTINGS 20
|
||||
extern matchsettingdef matchsettings[NUMMATCHSETTINGS];
|
||||
extern int matchsynced[NUMMATCHSETTINGS]; // client side: the values the server last announced
|
||||
extern void matchsettings_reset(); // everything back to the defaults
|
||||
@@ -263,6 +263,9 @@ struct poshist
|
||||
}
|
||||
};
|
||||
|
||||
#define MEDKIT_MAX 2
|
||||
#define MEDKIT_HEAL 33
|
||||
|
||||
class playerstate
|
||||
{
|
||||
public:
|
||||
@@ -272,8 +275,9 @@ public:
|
||||
bool akimbo;
|
||||
int ammo[NUMGUNS], mag[NUMGUNS], gunwait[NUMGUNS];
|
||||
int pstatshots[NUMGUNS], pstatdamage[NUMGUNS];
|
||||
int medkits; // carryable health pickups when matchmedkit is on (3rd-slot style usable item)
|
||||
|
||||
playerstate() : armour(0), primary(GUN_ASSAULT), nextprimary(GUN_ASSAULT), akimbo(false) {}
|
||||
playerstate() : armour(0), primary(GUN_ASSAULT), nextprimary(GUN_ASSAULT), akimbo(false), medkits(0) {}
|
||||
virtual ~playerstate() {}
|
||||
|
||||
void resetstats() { loopi(NUMGUNS) pstatshots[i] = pstatdamage[i] = 0; }
|
||||
@@ -297,12 +301,13 @@ public:
|
||||
|
||||
bool canpickup(int type)
|
||||
{
|
||||
extern int matchmedkit;
|
||||
switch(type)
|
||||
{
|
||||
case I_CLIPS: return ammo[akimbo && ammo[GUN_AKIMBO]<ammostats[GUN_AKIMBO].max ? GUN_AKIMBO : GUN_PISTOL]<ammostats[akimbo && ammo[GUN_AKIMBO]<ammostats[GUN_AKIMBO].max ? GUN_AKIMBO : GUN_PISTOL].max;
|
||||
case I_AMMO: return ammo[primary]<ammostats[primary].max;
|
||||
case I_GRENADE: return mag[GUN_GRENADE]<ammostats[GUN_GRENADE].max;
|
||||
case I_HEALTH: return health<powerupstats[type-I_HEALTH].max;
|
||||
case I_HEALTH: return matchmedkit ? medkits<MEDKIT_MAX : health<powerupstats[type-I_HEALTH].max;
|
||||
case I_HELMET:
|
||||
case I_ARMOUR: return armour<powerupstats[type-I_HEALTH].max;
|
||||
case I_AKIMBO: return !akimbo;
|
||||
@@ -326,7 +331,13 @@ public:
|
||||
break;
|
||||
case I_AMMO: additem(ammostats[primary], ammo[primary]); break;
|
||||
case I_GRENADE: additem(ammostats[GUN_GRENADE], mag[GUN_GRENADE]); break;
|
||||
case I_HEALTH: additem(powerupstats[type-I_HEALTH], health); break;
|
||||
case I_HEALTH:
|
||||
{
|
||||
extern int matchmedkit;
|
||||
if(matchmedkit) { if(medkits < MEDKIT_MAX) medkits++; }
|
||||
else additem(powerupstats[type-I_HEALTH], health);
|
||||
break;
|
||||
}
|
||||
case I_HELMET:
|
||||
case I_ARMOUR:
|
||||
additem(powerupstats[type-I_HEALTH], armour); break;
|
||||
@@ -344,6 +355,7 @@ public:
|
||||
armour = 0;
|
||||
gunselect = GUN_PISTOL;
|
||||
akimbo = false;
|
||||
medkits = 0;
|
||||
loopi(NUMGUNS) ammo[i] = mag[i] = gunwait[i] = 0;
|
||||
ammo[GUN_KNIFE] = mag[GUN_KNIFE] = 1;
|
||||
}
|
||||
@@ -612,6 +624,16 @@ public:
|
||||
{
|
||||
if(!w) return;
|
||||
extern int lastmillis;
|
||||
extern int matchreloadcancel;
|
||||
// cancelling a reload by switching: drop the pending reload, new weapon gets a 0.2s ready delay
|
||||
if(weaponsel && weaponsel->reloading && matchreloadcancel)
|
||||
{
|
||||
weaponsel->reloading = 0;
|
||||
weaponsel->gunwait = 0;
|
||||
// the 0.2s ready delay only applies to reloadable guns, so it can never sit in the way of
|
||||
// grenade cooking (knife/grenade shots are not affected by reloading) - see grenades::attack()
|
||||
if(reloadable_gun(w->type)) w->gunwait = max(w->gunwait, 200);
|
||||
}
|
||||
weaponsel->ondeselecting();
|
||||
weaponchanging = lastmillis;
|
||||
nextweaponsel = w;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
#### 20261025_22.19.30 #### scanning all map directories... found 0 official maps, 0 servermaps and 0 maps in 'incoming'
|
||||
+109
-6
@@ -5,6 +5,10 @@
|
||||
|
||||
#include "cube.h"
|
||||
|
||||
extern int matchbackwards;
|
||||
extern int matchknifeboost;
|
||||
extern int matchheadboost;
|
||||
|
||||
float raycube(const vec &o, const vec &ray, vec &surface)
|
||||
{
|
||||
surface = vec(0, 0, 0);
|
||||
@@ -341,6 +345,17 @@ bool collide(physent *d, bool spawn, float drop, float rise)
|
||||
{
|
||||
if(spacehi<-0.1) return true; // hack alert!
|
||||
if(spacelo>0.1f) d->o.z = hi-d->aboveeye; // glue to ceiling if in midair
|
||||
// head bump on a ceiling: small horizontal speed boost (matchheadboost)
|
||||
if(matchheadboost && d->vel.z > 0.5f && (d->type == ENT_PLAYER || d->type == ENT_BOT) && d->state == CS_ALIVE)
|
||||
{
|
||||
float hspeed = sqrtf(d->vel.x*d->vel.x + d->vel.y*d->vel.y);
|
||||
if(hspeed > 0.05f)
|
||||
{
|
||||
float boost = 1.06f;
|
||||
d->vel.x *= boost;
|
||||
d->vel.y *= boost;
|
||||
}
|
||||
}
|
||||
d->vel.z = 0; // cancel out jumping velocity
|
||||
}
|
||||
|
||||
@@ -398,6 +413,52 @@ FVARP(flyspeed, 1.0, 2.0, 5.0);
|
||||
extern int matchgravity;
|
||||
extern int matchspeedmul;
|
||||
extern int matchfriction;
|
||||
extern int matchsourcephysics;
|
||||
|
||||
// Source (Quake lineage) style movement, used when the "matchsourcephysics" match setting is on (off by default).
|
||||
// Ground: constant acceleration towards the wish direction plus Source's friction model.
|
||||
// Air: the classic air-strafe model - only a small part of the wish speed counts (sv_air_max_wishspeed),
|
||||
// so turning while strafing in the air keeps adding speed instead of just steering.
|
||||
// No friction in the air, and jumping the moment you land skips ground friction: that is what makes
|
||||
// bunny hopping work. Velocities here are in the same normalized unit as physent::vel (1.0 = maxspeed).
|
||||
#define SRC_ACCELERATE 10.0f // sv_accelerate
|
||||
#define SRC_AIRACCELERATE 11.0f // sv_airaccelerate (11 instead of 10: our physics runs at 200Hz instead of
|
||||
// Source's 66Hz, which makes small impulses add up to less speed gain -
|
||||
// this brings the gained speed per second back in line with Source)
|
||||
#define SRC_FRICTION 5.2f // sv_friction
|
||||
#define SRC_STOPSPEED 0.25f // sv_stopspeed (80 of sv_maxspeed 320)
|
||||
#define SRC_AIRWISHCAP 0.09375f // sv_air_max_wishspeed (30 of sv_maxspeed 320)
|
||||
|
||||
static inline void sourcefriction(vec &vel, float dt)
|
||||
{
|
||||
float speed = vel.magnitudexy();
|
||||
if(speed < 0.01f) return;
|
||||
float control = max(speed, SRC_STOPSPEED);
|
||||
float newspeed = max(speed - control*SRC_FRICTION*dt, 0.0f) / speed;
|
||||
vel.x *= newspeed;
|
||||
vel.y *= newspeed;
|
||||
}
|
||||
|
||||
static inline void sourceaccelerate(vec &vel, const vec &wishdir, float wishspeed, float dt)
|
||||
{
|
||||
float currentspeed = vel.x*wishdir.x + vel.y*wishdir.y;
|
||||
float addspeed = wishspeed - currentspeed;
|
||||
if(addspeed <= 0.0f) return;
|
||||
float accelspeed = min(SRC_ACCELERATE*wishspeed*dt, addspeed);
|
||||
vel.x += accelspeed*wishdir.x;
|
||||
vel.y += accelspeed*wishdir.y;
|
||||
}
|
||||
|
||||
static inline void sourceairaccelerate(vec &vel, const vec &wishdir, float wishspeed, float dt)
|
||||
{
|
||||
float wishspd = min(wishspeed, SRC_AIRWISHCAP);
|
||||
float currentspeed = vel.x*wishdir.x + vel.y*wishdir.y;
|
||||
float addspeed = wishspd - currentspeed;
|
||||
if(addspeed <= 0.0f) return;
|
||||
float accelspeed = min(SRC_AIRACCELERATE*wishspeed*dt, addspeed);
|
||||
vel.x += accelspeed*wishdir.x;
|
||||
vel.y += accelspeed*wishdir.y;
|
||||
}
|
||||
|
||||
void moveplayer(physent *pl, int moveres, bool local, int curtime)
|
||||
{
|
||||
@@ -405,6 +466,7 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime)
|
||||
const bool editfly = pl->state==CS_EDITING;
|
||||
const bool specfly = pl->type==ENT_PLAYER && ((playerent *)pl)->spectatemode==SM_FLY;
|
||||
const bool isfly = editfly || specfly;
|
||||
const bool srcphys = matchsourcephysics && pl->type==ENT_PLAYER; // players only: bots keep normal movement
|
||||
|
||||
vec d; // vector of direction we ideally want to move in
|
||||
|
||||
@@ -463,8 +525,11 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime)
|
||||
const float friction = (water ? 20.0f : (pl->onfloor || isfly ? 6.0f : (pl->onladder ? 1.5f : 30.0f))) * 100.0f / clamp(matchfriction, 10, 500);
|
||||
const float fpsfric = max(friction/curtime*20.0f, 1.0f);
|
||||
|
||||
d.x = (float)(move*cosf(RAD*(pl->yaw-90)));
|
||||
d.y = (float)(move*sinf(RAD*(pl->yaw-90)));
|
||||
// walking backwards is slower (70%): scale the backward input itself,
|
||||
// so backpedalling (and only backpedalling) loses speed
|
||||
float backmul = (matchbackwards && move < 0 && !isfly && !water) ? 0.7f : 1.0f;
|
||||
d.x = (float)(move*cosf(RAD*(pl->yaw-90)))*backmul;
|
||||
d.y = (float)(move*sinf(RAD*(pl->yaw-90)))*backmul;
|
||||
d.z = 0.0f;
|
||||
|
||||
if(isfly || water)
|
||||
@@ -479,9 +544,34 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime)
|
||||
|
||||
float curfullspeed = d.magnitudexy();
|
||||
|
||||
pl->vel.mul(fpsfric-1.0f); // slowly apply friction and direction to velocity, gives a smooth movement
|
||||
pl->vel.add(d);
|
||||
pl->vel.div(fpsfric);
|
||||
if(srcphys && !isfly && !water && !pl->onladder)
|
||||
{ // Source style: accelerate towards the wish direction, friction on the ground only
|
||||
vec wishdir(d.x, d.y, 0);
|
||||
float wishspeed = wishdir.magnitudexy();
|
||||
if(wishspeed > 1e-4f) { wishdir.x /= wishspeed; wishdir.y /= wishspeed; }
|
||||
else { wishdir.x = wishdir.y = 0; wishspeed = 0; }
|
||||
vec vel(pl->vel.x, pl->vel.y, 0);
|
||||
const float dt = curtime/1000.0f;
|
||||
// jumping straight off the floor skips friction: bunny hopping
|
||||
if(pl->onfloor && !pl->jumpnext)
|
||||
{
|
||||
sourcefriction(vel, dt);
|
||||
sourceaccelerate(vel, wishdir, wishspeed, dt);
|
||||
}
|
||||
else if(wishspeed > 1e-4f) sourceairaccelerate(vel, wishdir, wishspeed, dt);
|
||||
pl->vel.x = vel.x;
|
||||
pl->vel.y = vel.y;
|
||||
// The classic model lerps the whole velocity vector towards the wish direction, which also bleeds
|
||||
// off the vertical part of the jump impulse (the jump is a constant upward velocity here). Keep that
|
||||
// exact decay, or jumps go far too high and float: the horizontal model above is the only difference.
|
||||
pl->vel.z *= (fpsfric-1.0f)/fpsfric;
|
||||
}
|
||||
else
|
||||
{ // classic AssaultCube movement: slowly apply friction and direction to velocity, gives a smooth movement
|
||||
pl->vel.mul(fpsfric-1.0f);
|
||||
pl->vel.add(d);
|
||||
pl->vel.div(fpsfric);
|
||||
}
|
||||
d = pl->vel;
|
||||
d.mul(speed);
|
||||
|
||||
@@ -530,9 +620,19 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime)
|
||||
{
|
||||
pl->jumpd = true;
|
||||
pl->jumpnext = false;
|
||||
bool doublejump = pl->lastjump && lastmillis - pl->lastjump < 250 && pl->strafe != 0 && pl->o.z - pl->eyeheight - pl->lastjumpheight > 0.2f;
|
||||
bool doublejump = !srcphys && pl->lastjump && lastmillis - pl->lastjump < 250 && pl->strafe != 0 && pl->o.z - pl->eyeheight - pl->lastjumpheight > 0.2f;
|
||||
pl->lastjumpheight = pl->o.z - pl->eyeheight;
|
||||
pl->vel.z = 2.0f; // physics impulse upwards
|
||||
// knife + jump at the same time: very slight horizontal speed boost (matchknifeboost)
|
||||
if(matchknifeboost && pl->type == ENT_PLAYER)
|
||||
{
|
||||
playerent *pp = (playerent *)pl;
|
||||
if(pp->weaponsel && pp->weaponsel->type == GUN_KNIFE && (pp->attacking || lastmillis - pp->lastaction < 250))
|
||||
{
|
||||
pl->vel.x *= 1.10f;
|
||||
pl->vel.y *= 1.10f;
|
||||
}
|
||||
}
|
||||
if(doublejump && curfullspeed > 0.1f) // more velocity on double jump
|
||||
{
|
||||
pl->vel.mul(1.25f / max(pl->vel.magnitudexy() / curfullspeed, 1.0f));
|
||||
@@ -569,6 +669,9 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime)
|
||||
}
|
||||
|
||||
const float gravity = 20.0f * (matchgravity ? matchgravity / 100.0f : 1.0f);
|
||||
// NOTE: the timeinair term below is what makes AssaultCube players come back down at all (the jump
|
||||
// is a constant upward velocity, so the increasing drop is the "gravity"). Source physics only
|
||||
// changes the horizontal model - the vertical one has to stay exactly like this, or jumps turn floaty.
|
||||
float dropf = (gravity-1)+pl->timeinair/15.0f; // incorrect, but works fine
|
||||
if(water) { dropf = 5; pl->timeinair = 0; } // float slowly down in water
|
||||
if(pl->onladder) { dropf = 0; pl->timeinair = 0; }
|
||||
|
||||
Binary file not shown.
@@ -621,7 +621,7 @@ static const int msgsizes[] = // size inclusive message token, 0 f
|
||||
SV_PAUSEMODE, 1,
|
||||
SV_GETVITA, 2, SV_VITADATA, 0,
|
||||
SV_DEATHBLAST, 2,
|
||||
SV_MATCHSET, 3,
|
||||
SV_MATCHSET, 3, SV_MEDKIT, 1,
|
||||
-1
|
||||
};
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#define CUBE_SERVINFO_PORT(serverport) (serverport+1)
|
||||
#define CUBE_SERVINFO_TO_SERV_PORT(servinfoport) (servinfoport-1)
|
||||
#define CLIENTIPCENSOR 12 // blank out the last 12 bits of client's IPs before telling them to others (compromise between "16" from AC 0.9x and "8" from AC 1.1)
|
||||
#define PROTOCOL_VERSION 1303 // bump when protocol changes (use negative numbers for mods!) - FORK VERSION
|
||||
#define PROTOCOL_VERSION 1304 // bump when protocol changes (use negative numbers for mods!) - FORK VERSION
|
||||
#define DEMO_VERSION 2 // bump when demo format changes
|
||||
#define DEMO_MAGIC "ASSAULTCUBE_DEMO"
|
||||
#define DEMO_MINTIME 10000 // don't keep demo recordings with less than 10 seconds
|
||||
@@ -53,6 +53,7 @@ enum
|
||||
SV_GETVITA, SV_VITADATA,
|
||||
SV_DEATHBLAST,
|
||||
SV_MATCHSET, SV_MATCHSETTINGS,
|
||||
SV_MEDKIT,
|
||||
SV_NUM
|
||||
};
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ VARP(hideeditinfopanel, 0, 0, 1);
|
||||
VARP(hidevote, 0, 0, 2);
|
||||
VARP(hidehudmsgs, 0, 0, 1);
|
||||
VARP(hidehudequipment, 0, 0, 1);
|
||||
VARP(showgrenadebar, 0, 1, 1);
|
||||
VARP(hideconsole, 0, 0, 1);
|
||||
VARP(hidespecthud, 0, 0, 1);
|
||||
VAR(showmap, 0, 0, 1);
|
||||
@@ -322,6 +323,7 @@ void drawktfindicator(playerent *p)
|
||||
}
|
||||
|
||||
extern int oldfashionedgunstats;
|
||||
extern int matchmedkit;
|
||||
|
||||
int getprevweaponsel(playerent *p) // get previous weapon or, if we don't know it, get the primary
|
||||
{
|
||||
@@ -348,6 +350,58 @@ void drawequipicons(playerent *p)
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
// grenade cooking indicator: a thin ring around the crosshair that fills up white->red
|
||||
// while the fuse burns (same flat-shaded style as the damage direction indicator)
|
||||
void drawgrenadecookring(playerent *p)
|
||||
{
|
||||
if(!showgrenadebar || p->state != CS_ALIVE) return;
|
||||
if(!p->weapons[GUN_GRENADE]) return;
|
||||
grenades *g = (grenades *)p->weapons[GUN_GRENADE];
|
||||
extern int lastmillis;
|
||||
float progress = -1.0f;
|
||||
if(p == player1)
|
||||
{
|
||||
if(g->state == GST_INHAND && g->inhandnade)
|
||||
progress = clamp((lastmillis - g->inhandnade->millis) / 2000.0f, 0.0f, 1.0f);
|
||||
}
|
||||
else if(g->state == GST_INHAND)
|
||||
{
|
||||
progress = clamp((lastmillis - g->throwmillis) / 2000.0f, 0.0f, 1.0f);
|
||||
}
|
||||
if(progress < 0.0f) return;
|
||||
const float TAU = 6.2831853f;
|
||||
float cx = VIRTW/2, cy = VIRTH/2;
|
||||
float r0 = 30.0f, r1 = 33.5f;
|
||||
const int segs = 40;
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
// faint full-circle track
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.18f);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
loopi(segs+1)
|
||||
{
|
||||
float a = -PI/2.0f + (i/(float)segs)*TAU;
|
||||
float c = cosf(a), s = sinf(a);
|
||||
glVertex2f(cx + c*r1, cy + s*r1);
|
||||
glVertex2f(cx + c*r0, cy + s*r0);
|
||||
}
|
||||
glEnd();
|
||||
// burnt fuse: white -> red as it cooks
|
||||
int n = max(2, int(progress*segs));
|
||||
glColor4f(1.0f, 1.0f - progress*0.85f, 1.0f - progress*0.9f, 0.9f);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
loopi(n+1)
|
||||
{
|
||||
float a = -PI/2.0f + (i/(float)segs)*TAU;
|
||||
float c = cosf(a), s = sinf(a);
|
||||
glVertex2f(cx + c*r1, cy + s*r1);
|
||||
glVertex2f(cx + c*r0, cy + s*r0);
|
||||
}
|
||||
glEnd();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void drawradarent(float x, float y, float yaw, int col, int row, float iconsize, bool pulse, const char *label = NULL, ...) PRINTFARGS(8, 9);
|
||||
|
||||
void drawradarent(float x, float y, float yaw, int col, int row, float iconsize, bool pulse, const char *label, ...)
|
||||
@@ -818,6 +872,14 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat
|
||||
if(damageindicatorplayer == p || (is_spect && getclient(player1->followplayercn) == damageindicatorplayer)) drawdmgindicator(p);
|
||||
|
||||
if(p->state==CS_ALIVE && !hidehudequipment) drawequipicons(p);
|
||||
if(p->state==CS_ALIVE && !editmode && !showmap)
|
||||
{
|
||||
glLoadIdentity();
|
||||
glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
|
||||
drawgrenadecookring(p);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, VIRTW*2, VIRTH*2, 0, -1, 1);
|
||||
}
|
||||
|
||||
if(!editmode)
|
||||
{
|
||||
@@ -1102,6 +1164,12 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat
|
||||
{
|
||||
pushfont("huddigits");
|
||||
draw_textf("%d", HUDPOS_HEALTH + HUDPOS_NUMBERSPACING, 823, p->health);
|
||||
if(matchmedkit && p->medkits > 0) // medkit stock, same digits as the health number
|
||||
{
|
||||
defformatstring(hp)("%d", p->health);
|
||||
int hw = text_width(hp);
|
||||
draw_textf("\f2%d", HUDPOS_HEALTH + HUDPOS_NUMBERSPACING + hw + 14, 823, p->medkits);
|
||||
}
|
||||
if(p->armour) draw_textf("%d", HUDPOS_ARMOUR + HUDPOS_NUMBERSPACING, 823, p->armour);
|
||||
if(p->weaponsel && valid_weapon(p->weaponsel->type))
|
||||
{
|
||||
|
||||
+27
-1
@@ -47,6 +47,14 @@ int matchdeathpower = 100; // blast damage, % of the default (75% of a grenade
|
||||
// movement/weapon feel: the clients apply these, the server only hands them out
|
||||
int matchrecoilmul = 100, matchspreadmul = 100, matchspeedmul = 100, matchgravity = 100, matchfriction = 100;
|
||||
|
||||
// movement/gadget feel, part 2
|
||||
int matchreloadcancel = 1; // allow cancelling reloads by switching weapons (0.2s switch delay)
|
||||
int matchknifeboost = 0; // knife attack + jump at the same time gives a slight speed boost
|
||||
int matchmedkit = 0; // health pickups become carryable medkits (use with "usemedkit")
|
||||
int matchbackwards = 1; // walking backwards moves at 70% speed
|
||||
int matchheadboost = 1; // bumping your head on a ceiling gives a small speed boost
|
||||
int matchsourcephysics = 0; // Source/Quake style movement: air strafing, bunny hopping, no air friction
|
||||
|
||||
// The order of this table is part of the protocol (SV_MATCHSET sends an index, SV_MATCHSETTINGS all values in this order).
|
||||
matchsettingdef matchsettings[NUMMATCHSETTINGS] =
|
||||
{
|
||||
@@ -63,7 +71,13 @@ matchsettingdef matchsettings[NUMMATCHSETTINGS] =
|
||||
{ "matchspawnprimary", &matchspawnprimary, -1, -1, NUMGUNS-1 },
|
||||
{ "matchspawnsecondary", &matchspawnsecondary, -1, -1, NUMGUNS-1 },
|
||||
{ "matchspawntertiary", &matchspawntertiary, -1, -1, NUMGUNS-1 },
|
||||
{ "matchspawnquaternary", &matchspawnquaternary,-1, -1, NUMGUNS-1 }
|
||||
{ "matchspawnquaternary", &matchspawnquaternary,-1, -1, NUMGUNS-1 },
|
||||
{ "matchreloadcancel", &matchreloadcancel, 0, 1, 1 },
|
||||
{ "matchknifeboost", &matchknifeboost, 0, 0, 1 },
|
||||
{ "matchmedkit", &matchmedkit, 0, 0, 1 },
|
||||
{ "matchbackwards", &matchbackwards, 0, 1, 1 },
|
||||
{ "matchheadboost", &matchheadboost, 0, 1, 1 },
|
||||
{ "matchsourcephysics", &matchsourcephysics, 0, 0, 1 }
|
||||
};
|
||||
int matchsynced[NUMMATCHSETTINGS];
|
||||
|
||||
@@ -3909,6 +3923,18 @@ void process(ENetPacket *packet, int sender, int chan)
|
||||
break;
|
||||
}
|
||||
|
||||
case SV_MEDKIT:
|
||||
{
|
||||
if(matchmedkit && cl && cl->state.state == CS_ALIVE && cl->state.medkits > 0 && cl->state.health < 100)
|
||||
{
|
||||
cl->state.medkits--;
|
||||
cl->state.health += 33;
|
||||
if(cl->state.health > 100) cl->state.health = 100;
|
||||
sendf(-1, 1, "ri7", SV_DAMAGE, sender, sender, GUN_KNIFE, 0, cl->state.armour, cl->state.health);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SV_PING:
|
||||
sendf(sender, 1, "ii", SV_PONG, getint(p));
|
||||
break;
|
||||
|
||||
+1
-1
@@ -457,7 +457,7 @@ const char *messagenames[SV_NUM] =
|
||||
"SV_EXTENSION",
|
||||
"SV_MAPIDENT", "SV_DEMOCHECKSUM", "SV_DEMOSIGNATURE",
|
||||
"SV_PAUSEMODE",
|
||||
"SV_GETVITA", "SV_VITADATA", "SV_DEATHBLAST", "SV_MATCHSET", "SV_MATCHSETTINGS"
|
||||
"SV_GETVITA", "SV_VITADATA", "SV_DEATHBLAST", "SV_MATCHSET", "SV_MATCHSETTINGS", "SV_MEDKIT"
|
||||
};
|
||||
|
||||
const char *entnames[] =
|
||||
|
||||
+21
-2
@@ -127,6 +127,7 @@ void quicknadethrow(bool on)
|
||||
if(player1->state != CS_ALIVE) return;
|
||||
if(on)
|
||||
{
|
||||
quicknade = false; // a new quick-nade press always starts from a clean state
|
||||
if(player1->weapons[GUN_GRENADE]->mag > 0)
|
||||
{
|
||||
if(player1->weaponsel->type != GUN_GRENADE) selectweapon(player1->weapons[GUN_GRENADE]);
|
||||
@@ -173,6 +174,22 @@ void tryreload(playerent *p)
|
||||
|
||||
COMMANDF(reload, "", () { tryreload(player1); });
|
||||
|
||||
extern int matchmedkit;
|
||||
|
||||
void tryusemedkit(playerent *p)
|
||||
{
|
||||
if(!p || p->state != CS_ALIVE || ispaused || intermission) return;
|
||||
if(!matchmedkit || p->medkits <= 0 || p->health >= 100) return;
|
||||
p->medkits--;
|
||||
p->health += MEDKIT_HEAL;
|
||||
if(p->health > 100) p->health = 100;
|
||||
audiomgr.playsoundc(S_ITEMHEALTH, p);
|
||||
addmsg(SV_MEDKIT, "");
|
||||
}
|
||||
|
||||
COMMANDF(usemedkit, "", () { tryusemedkit(player1); });
|
||||
COMMANDF(medkitcount, "", () { intret(player1 ? player1->medkits : 0); });
|
||||
|
||||
void createrays(const vec &from, const vec &to) // create random spread of rays for the shotgun
|
||||
{
|
||||
vec dir = vec(from).sub(to);
|
||||
@@ -1046,6 +1063,7 @@ VARP(righthanded, 0, 1, 1); // flowtron 20090727
|
||||
// the server, see matchset below) and everybody else's local changes are undone right away, so nobody can give themselves
|
||||
// no recoil or low gravity. In offline/bot games you're the host and may set them freely.
|
||||
extern int matchrecoilmul, matchspreadmul;
|
||||
extern int matchreloadcancel;
|
||||
|
||||
static void matchsettingchanged()
|
||||
{
|
||||
@@ -1145,7 +1163,7 @@ void weapon::renderaimhelp(bool teamwarning)
|
||||
int weapon::dynspread() { return int(info.spread * matchspreadmul / 100.0f); }
|
||||
float weapon::dynrecoil() { return info.recoil * matchrecoilmul / 100.0f; }
|
||||
bool weapon::selectable() { return this != owner->weaponsel && owner->state == CS_ALIVE && !owner->weaponchanging; }
|
||||
bool weapon::deselectable() { return !reloading; }
|
||||
bool weapon::deselectable() { return !reloading || matchreloadcancel; }
|
||||
|
||||
void weapon::equipplayer(playerent *pl)
|
||||
{
|
||||
@@ -1400,7 +1418,8 @@ void grenades::thrownade(const vec &vel)
|
||||
updatelastaction(owner);
|
||||
state = GST_THROWING;
|
||||
if(this==owner->weaponsel) owner->attacking = false;
|
||||
if(quicknade && owner->weaponsel->type == GUN_GRENADE) selectweapon(owner->prevweaponsel);
|
||||
if(quicknade && owner->weaponsel->type == GUN_GRENADE && owner->prevweaponsel && owner->prevweaponsel != this)
|
||||
selectweapon(owner->prevweaponsel);
|
||||
}
|
||||
|
||||
void grenades::dropnade()
|
||||
|
||||
Reference in New Issue
Block a user