fun changes

This commit is contained in:
kai
2026-10-25 23:11:15 +00:00
parent cbe737524d
commit f7ceb38f6b
15 changed files with 271 additions and 17 deletions
+6
View File
@@ -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 ]
+2
View File
@@ -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
+2 -1
View File
@@ -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
+4
View File
@@ -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
View File
@@ -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;
+2
View File
@@ -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
View File
@@ -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.
+1 -1
View File
@@ -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
};
+2 -1
View File
@@ -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
};
+68
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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()