- Balance:
0) Playtest current weapons and armours.
1) Playtest the bots (old AI).
+ 2) Modify armour type based on maximum.
- HUD:
0) Add accuracy, frags, deaths, suicides and more.
1) Add accuracy per weapon, with icons.
#include "game.h"
+int pwitemspicked[7] = { 0 };
+
namespace entities
{
using namespace game;
}
playsound(itemstats[type-I_SHELLS].sound, d!=h ? &d->o : NULL, NULL, 0, 0, 0, -1, 0, 1500);
d->pickup(type);
+ switch(type) {
+ case I_TINYARMOUR: pwitemspicked[0]++; break;
+ case I_GREENARMOUR: pwitemspicked[1]++; break;
+ case I_YELLOWARMOUR: pwitemspicked[2]++; break;
+ case I_TINYHEALTH: pwitemspicked[3]++; break;
+ case I_HEALTH: pwitemspicked[4]++; break;
+ case I_BOOST: pwitemspicked[5]++; break;
+ case I_QUAD: pwitemspicked[6]++; break;
+ }
if(d==h) switch(type)
{
case I_BOOST:
void startmap(const char *name) // called just after a map load
{
+ pwreset();
ai::savewaypoints();
ai::clearwaypoints(true);
flushhudmatrix();
defformatstring(label, "%d", p->ammo[gun]);
- int tw, th; text_bounds(label, tw, th);
+ int tw, th, moved, movew = 0, moveh = 0; text_bounds(label, tw, th);
vec2 textdrawpos = vec2(-tw, -th).div(2);
float ammoratio = (float)p->ammo[gun] / itemstats[gun-GUN_SG].add;
bvec color = bvec::hexcolor(p->ammo[gun] == 0 || ammoratio >= 1.0f ? 0xFFFFFF : (ammoratio >= 0.5f ? 0xFFC040 : 0xFF0000));
draw_text(label, textdrawpos.x, textdrawpos.y, color.r, color.g, color.b, alpha);
+ /// ALIGN STUFF AND ADD COMMAND FOR IT...
+ //~text_bounds(label, movew, moveh);
+ //~moved = movew + 6;
+ //~defformatstring(damagedealt, "| %d ", pwdamagedealt[gun]);
+ //~draw_text(damagedealt, textdrawpos.x+moved, textdrawpos.y, color.r, color.g, color.b, alpha);
+ //~text_bounds(damagedealt, movew, moveh);
+ //~moved += movew;
+ //~defformatstring(accuracy, "| %d %%", pwaccuracy[gun]);
+ //~draw_text(accuracy, textdrawpos.x+moved, textdrawpos.y, color.r, color.g, color.b, alpha);
pophudmatrix();
}
{ S_RLFIRE, 800, 120, 0, 270, 10, 1024, 1, 160, 40, 0, "rocketlauncher", "rocket", 0 },
{ S_RIFLE, 1200, 120, 0, 0, 30, 2048, 1, 80, 0, 0, "rifle", "rifle", 0 },
{ S_FLAUNCH, 600, 90, 0, 300, 20, 1024, 1, 250, 45, 1500, "grenadelauncher", "gl", 0 },
- { S_PISTOL, 400, 60, 160, 0, 10, 1024, 1, 80, 0, 0, "pistol", "pistol", 0 },
+ { S_PISTOL, 400, 60, 110, 0, 10, 1024, 1, 80, 0, 0, "pistol", "pistol", 0 },
};
+/// Rough accuracy code, client-side only.
+
+extern int pwshotsfired[NUMGUNS];
+extern int pwshotshit[NUMGUNS];
+extern int pwdamagedealt[NUMGUNS];
+extern int pwaccuracy[NUMGUNS];
+extern int pwavgaccuracy;
+extern int pwitemspicked[7];
+
+extern void pwshot(int gun);
+extern void pwhit(int gun, int damage);
+extern void pwcalcaccuracy(void);
+extern void pwreset(void);
+
#include "ai.h"
// inherited by fpsent and server clients
[[fallthrough]];
case I_YELLOWARMOUR: return maxarmour<is.max || armour<maxarmour;
- //~case I_TINYARMOUR:
- //~if(armourtype==A_GREEN || armourtype==A_YELLOW || armour>=50)return false;
- //~case I_GREENARMOUR:
- //~// (100h/100g only absorbs 200 damage)
- //~if(armourtype==A_YELLOW && armour>=100)return false;
- //~case I_YELLOWARMOUR: return !armourtype || armour<is.max;
case I_QUAD: return quadmillis<is.max;
default: return ammo[is.info]<is.max;
}
case I_TINYHEALTH:
health = min(health+is.add, maxhealth);
break;
- //~case I_TINYARMOUR:
- //~armour = min(armour+is.add, is.max);
- //~armourtype = A_BLUE;
- //~break;
case I_BOOST:
maxhealth = min(maxhealth+is.info, is.max);
- [[fallthrough]];
+ [[fallthrough]];
case I_HEALTH: // boost also adds to health
health = min(health+is.add, maxhealth);
break;
armour = min(armour+is.add, maxarmour);
armourtype = is.info;
break;
- //~case I_GREENARMOUR:
- //~case I_YELLOWARMOUR:
- //~armour = min(armour+is.add, is.max);
- //~armourtype = is.info;
- //~break;
case I_QUAD:
quadmillis = min(quadmillis+is.add, is.max);
break;
{
armourtype = A_GREEN;
armour = 100;
- loopi(5) baseammo(i+1);
+ loopi(NUMGUNS-1) baseammo(i+1);
gunselect = GUN_CG;
ammo[GUN_CG] /= 2;
}
armourtype = A_BLUE;
armour = 25;
ammo[GUN_PISTOL] = 40;
- ammo[GUN_GL] = 1;
}
}
// just subtract damage here, can set death, etc. later in code calling this
int dodamage(int damage)
{
- int ad = (damage*(armourtype+1)*25)/100; // let armour absorb when possible
+ int ad = (damage*(armourtype+1)*30)/100; // let armour absorb when possible
if(ad>armour) ad = armour;
armour -= ad;
damage -= ad;
{
VARP(scoreboard2d, 0, 1, 1);
VARP(showservinfo, 0, 1, 1);
- VARP(showclientnum, 0, 0, 1);
+ VARP(showclientnum, 0, 1, 1);
VARP(showpj, 0, 0, 1);
VARP(showping, 0, 1, 2);
VARP(showspectators, 0, 1, 1);
- VARP(showspectatorping, 0, 0, 1);
+ VARP(showspectatorping, 0, 1, 1);
VARP(highlightscore, 0, 1, 1);
VARP(showconnecting, 0, 0, 1);
- VARP(hidefrags, 0, 1, 1);
- VARP(showdeaths, 0, 0, 1);
+ VARP(hidefrags, 0, 0, 1);
+ VARP(showdeaths, 0, 1, 1);
+ VARP(showdamagedealt, 0, 1, 1);
static hashset<teaminfo> teaminfos;
g.poplist();
}
+ if(showdamagedealt)
+ {
+ g.pushlist();
+ g.strut(7);
+ g.text("damage", fgcolor);
+ loopscoregroup(o, g.textf("%d", 0xFFFFDD, NULL, o->totaldamage));
+ g.poplist();
+ }
+
g.pushlist();
g.text("name", fgcolor);
g.strut(12);
- loopscoregroup(o,
- {
- g.textf("%s ", statuscolor(o, 0xFFFFDD), NULL, colorname(o));
- });
+ loopscoregroup(o, { g.textf("%s ", statuscolor(o, 0xFFFFDD), NULL, colorname(o)); });
g.poplist();
if(multiplayer(false) || demoplayback)
}
}
}
+
+ /// PW
+ g.separator();
+ g.pushlist();
+ g.textf(" %d%% ", 0x787878, "chainsaw.png", pwaccuracy[0]);
+ g.textf(" %d%% ", 0xfba6a6, "shotgun.png", pwaccuracy[1]);
+ g.textf(" %d%% ", 0x7bc77a, "chaingun.png", pwaccuracy[2]);
+ g.textf(" %d%% ", 0xefd7a6, "rocket_launcher.png", pwaccuracy[3]);
+ g.textf(" %d%% ", 0x8f91e7, "rifle.png", pwaccuracy[4]);
+ g.textf(" %d%% ", 0x9ee5e5, "grenade_launcher.png", pwaccuracy[5]);
+ g.textf(" %d%% ", 0xc3c3c3, "pistol.png", pwaccuracy[6]);
+ g.poplist();
+ g.separator();
+ g.pushlist();
+ g.textf(" x %d ", 0xffffff, "blue_armour.png", pwitemspicked[0]);
+ g.textf(" x %d ", 0xffffff, "green_armour.png", pwitemspicked[1]);
+ g.textf(" x %d ", 0xffffff, "yellow_armour.png", pwitemspicked[2]);
+ g.textf(" x %d ", 0xffffff, "tiny_health.png", pwitemspicked[3]);
+ g.textf(" x %d ", 0xffffff, "health.png", pwitemspicked[4]);
+ g.textf(" x %d ", 0xffffff, "health_boost.png", pwitemspicked[5]);
+ g.textf(" x %d ", 0xffffff, "quad_damage.png", pwitemspicked[6]);
+ g.poplist();
}
struct scoreboardgui : g3d_callback
if(f->type==ENT_AI || !m_mp(gamemode) || f==at) f->hitpush(damage, vel, at, gun);
+ pwhit(gun, damage);
+
if(!m_mp(gamemode)) damaged(damage, f, at);
else
{
}
if(d->gunselect) d->ammo[d->gunselect]--;
+ pwshot(d->gunselect); /// PW
+
vec from = d->o, to = targ, dir = vec(to).sub(from).safenormalize();
float dist = to.dist(from);
vec kickback = vec(dir).mul(guns[d->gunselect].kickamount*-2.5f);
hits.length(), hits.length()*sizeof(hitmsg)/sizeof(int), hits.getbuf());
}
- d->gunwait = guns[d->gunselect].attackdelay;
- if(d->gunselect == GUN_PISTOL && d->ai) d->gunwait += int(d->gunwait*(((101-d->skill)+rnd(111-d->skill))/100.f));
+ d->gunwait = guns[d->gunselect].attackdelay;
+ if(d->gunselect == GUN_PISTOL && d->ai) d->gunwait += int(d->gunwait*(((101-d->skill)+rnd(111-d->skill))/100.f));
d->totalshots += guns[d->gunselect].damage*(d->quadmillis ? 4 : 1)*guns[d->gunselect].rays;
}
void updateweapons(int curtime)
{
updateprojectiles(curtime);
+ pwcalcaccuracy();
if(player1->clientnum>=0 && player1->state==CS_ALIVE) shoot(player1, worldpos); // only shoot when connected to server
updatebouncers(curtime); // need to do this after the player shoots so grenades don't end up inside player's BB next frame
fpsent *following = followingplayer();
}
};
+/// Rough accuracy code, client-side only.
+
+int pwshotsfired [NUMGUNS] = { 0 };
+int pwshotshit [NUMGUNS] = { 0 };
+int pwdamagedealt [NUMGUNS] = { 0 };
+int pwaccuracy [NUMGUNS] = { 0 };
+int pwavgaccuracy = 0;
+
+void pwshot(int gun) {
+ pwshotsfired[gun]++;
+}
+
+void pwhit(int gun, int damage) {
+ pwshotshit[gun]++;
+ pwdamagedealt[gun] += damage;
+}
+
+void pwcalcaccuracy(void) {
+ pwavgaccuracy = 0;
+ loopi(NUMGUNS)
+ if(pwshotsfired[i])
+ pwaccuracy[i] = (pwdamagedealt[i] * 100) / (guns[i].damage * guns[i].rays * pwshotsfired[i]);
+ else
+ pwaccuracy[i] = 0;
+ loopi(NUMGUNS) pwavgaccuracy += pwaccuracy[i];
+ pwavgaccuracy /= NUMGUNS;
+}
+
+void pwreset(void) {
+ loopi(NUMGUNS) pwshotsfired[i] = pwshotshit[i] = pwdamagedealt[i] = pwaccuracy[i] = 0;
+ loopi(7) pwitemspicked[i] = 0;
+ pwavgaccuracy = 0;
+}