if(superTime)
addPowerupItem("Superweapons", "superweapons", autocvar_hud_progressbar_superweapons_color, superTime, 30);
- entity item;
- for(item = Buff_Type_first; item; item = item.enemy)
- if(allBuffs & item.items)
- addPowerupItem(item.message, strcat("buff_", item.netname), item.colormod, bound(0, getstatf(STAT_BUFF_TIME) - time, 99), 60);
+ FOREACH(BUFFS, 0, BUFFS_COUNT,
+ it.m_itemid & allBuffs,
+ LAMBDA(
+ addPowerupItem(it.m_prettyName, strcat("buff_", it.m_name), it.m_color, bound(0, getstatf(STAT_BUFF_TIME) - time, 99), 60);
+ )
+ );
if(!powerupItemsCount)
return;
int row = 0;
draw_beginBoldFont();
- for(item = powerupItems; item.count; item = item.chain)
+ for(entity item = powerupItems; item.count; item = item.chain)
{
itemPos = eX * (pos.x + column * itemSize.x) + eY * (pos.y + row * itemSize.y);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
CALL_ACCUMULATED_FUNCTION(RegisterHUD_Panels);
- CALL_ACCUMULATED_FUNCTION(RegisterBuffs);
WaypointSprite_Load();
string spritelookuptext(string s)
{
if(substring(s, 0, 4) == "wpn-") { return (get_weaponinfo(stof(substring(s, 4, strlen(s)))).message); }
- if(substring(s, 0, 5) == "buff-") { return Buff_PrettyName(Buff_Type_FromSprite(s)); }
+ if (substring(s, 0, 5) == "buff-")
+ {
+ entity buff = BUFF_NULL;
+ FOREACH(BUFFS, 0, BUFFS_COUNT,
+ it.m_sprite == s,
+ LAMBDA({
+ buff = it;
+ break;
+ })
+ );
+ return buff.m_prettyName;
+ }
switch(s)
{
#if defined(CSQC)
#include "../dpdefs/csprogsdefs.qh"
#include "../client/defs.qh"
- #include "buffs.qh"
#elif defined(MENUQC)
#elif defined(SVQC)
#include "../dpdefs/progsdefs.qh"
#include "../dpdefs/dpextensions.qh"
- #include "buffs.qh"
#endif
+#include "buffs.qh"
-vector Buff_Color(int buff_id)
-{
- entity e;
- for(e = Buff_Type_first; e; e = e.enemy)
- if(buff_id == e.items)
- return e.colormod;
- return '1 1 1';
-}
-
-string Buff_PrettyName(int buff_id)
-{
- entity e;
- for(e = Buff_Type_first; e; e = e.enemy)
- if(buff_id == e.items)
- return e.message;
- return "";
-}
-
-string Buff_Name(int buff_id)
-{
- entity e;
- for(e = Buff_Type_first; e; e = e.enemy)
- if(buff_id == e.items)
- return e.netname;
- return "";
-}
-
-int Buff_Type_FromName(string buff_name)
-{
- entity e;
- for(e = Buff_Type_first; e; e = e.enemy)
- if(buff_name == e.netname)
- return e.items;
- return 0;
-}
-
-int Buff_Type_FromSprite(string buff_sprite)
-{
- entity e;
- for(e = Buff_Type_first; e; e = e.enemy)
- if(buff_sprite == e.model2)
- return e.items;
- return 0;
-}
-
-int Buff_Skin(int buff_id)
-{
- entity e;
- for(e = Buff_Type_first; e; e = e.enemy)
- if(buff_id == e.items)
- return e.skin;
- return 0;
-}
-
-string Buff_Sprite(int buff_id)
-{
- entity e;
- for(e = Buff_Type_first; e; e = e.enemy)
- if(buff_id == e.items)
- return e.model2;
- return "";
-}
-
-float Buff_Timer(int buff_id)
-{
- entity e;
- for(e = Buff_Type_first; e; e = e.enemy)
- if(buff_id == e.items)
- return e.buff_time;
- return 0;
-}
#include "teams.qh"
#include "util.qh"
-entity Buff_Type_first;
-entity Buff_Type_last;
-.entity enemy; // internal next pointer
-
-int BUFF_LAST = 1;
-int BUFF_ALL;
-
-.int items; // buff ID
-.string netname; // buff name
-.string message; // human readable name
-.vector colormod; // buff color
-.string model2; // buff sprite
-.int skin; // buff skin
-.float buff_time;
-
-// hacky function to return the cvar value only to server - TODO: do this properly!
-float sv_cvar(string cvarname)
-{
+#include "registry.qh"
+
+void RegisterBuffs();
+const int BUFFS_MAX = 16;
+entity BUFFS[BUFFS_MAX];
+int BUFFS_COUNT;
+#define REGISTER_BUFF(id) \
+ REGISTER(RegisterBuffs, BUFF, BUFFS, BUFFS_COUNT, id, Buff, m_id); \
+ REGISTER_INIT_POST(BUFF, id) { \
+ this.netname = this.m_name; \
+ this.m_itemid = BIT(this.m_id - 1); \
+ this.m_sprite = strzone(strcat("buff-", this.m_name)); \
+ } \
+ REGISTER_INIT(BUFF, id)
+REGISTER_REGISTRY(RegisterBuffs)
+
+#include "items/item/pickup.qh"
+CLASS(Buff, Pickup)
+ /** bit index */
+ ATTRIB(Buff, m_itemid, int, 0)
+ ATTRIB(Buff, m_name, string, "buff")
+ ATTRIB(Buff, m_color, vector, '1 1 1')
+ ATTRIB(Buff, m_prettyName, string, "Buff")
+ ATTRIB(Buff, m_skin, int, 0)
+ ATTRIB(Buff, m_sprite, string, "")
#ifdef SVQC
- return cvar(cvarname);
-#else
- return 0;
+ METHOD(Buff, m_time, float(entity))
+ float Buff_m_time(entity this) { return cvar(strcat("g_buffs_", this.netname, "_time")); }
#endif
+ENDCLASS(Buff)
+
+REGISTER_BUFF(NULL);
+
+REGISTER_BUFF(AMMO) {
+ this.m_prettyName = _("Ammo");
+ this.m_name = "ammo";
+ this.m_skin = 3;
+ this.m_color = '0.76 1 0.1';
+}
+
+REGISTER_BUFF(RESISTANCE) {
+ this.m_prettyName = _("Resistance");
+ this.m_name = "resistance";
+ this.m_skin = 0;
+ this.m_color = '0.36 1 0.07';
+}
+
+REGISTER_BUFF(SPEED) {
+ this.m_prettyName = _("Speed");
+ this.m_name = "speed";
+ this.m_skin = 9;
+ this.m_color = '0.1 1 0.84';
+}
+
+REGISTER_BUFF(MEDIC) {
+ this.m_prettyName = _("Medic");
+ this.m_name = "medic";
+ this.m_skin = 1;
+ this.m_color = '1 0.12 0';
+}
+
+REGISTER_BUFF(BASH) {
+ this.m_prettyName = _("Bash");
+ this.m_name = "bash";
+ this.m_skin = 5;
+ this.m_color = '1 0.39 0';
+}
+
+REGISTER_BUFF(VAMPIRE) {
+ this.m_prettyName = _("Vampire");
+ this.m_name = "vampire";
+ this.m_skin = 2;
+ this.m_color = '1 0 0.24';
+}
+
+REGISTER_BUFF(DISABILITY) {
+ this.m_prettyName = _("Disability");
+ this.m_name = "disability";
+ this.m_skin = 7;
+ this.m_color = '0.94 0.3 1';
+}
+
+REGISTER_BUFF(VENGEANCE) {
+ this.m_prettyName = _("Vengeance");
+ this.m_name = "vengeance";
+ this.m_skin = 15;
+ this.m_color = '1 0.23 0.61';
+}
+
+REGISTER_BUFF(JUMP) {
+ this.m_prettyName = _("Jump");
+ this.m_name = "jump";
+ this.m_skin = 10;
+ this.m_color = '0.24 0.78 1';
+}
+
+REGISTER_BUFF(FLIGHT) {
+ this.m_prettyName = _("Flight");
+ this.m_name = "flight";
+ this.m_skin = 11;
+ this.m_color = '0.33 0.56 1';
}
-#define REGISTER_BUFF(hname,sname,NAME,bskin,bcolor) \
- int BUFF_##NAME; \
- entity Buff_Type##sname; \
- void RegisterBuffs_##sname() \
- { \
- BUFF_##NAME = BUFF_LAST * 2; \
- BUFF_LAST = BUFF_##NAME; \
- BUFF_ALL |= BUFF_##NAME; \
- Buff_Type##sname = spawn(); \
- Buff_Type##sname.items = BUFF_##NAME; \
- Buff_Type##sname.netname = #sname; \
- Buff_Type##sname.message = hname; \
- Buff_Type##sname.skin = bskin; \
- Buff_Type##sname.colormod = bcolor; \
- Buff_Type##sname.buff_time = sv_cvar(strcat("g_buffs_", #sname, "_time")); \
- Buff_Type##sname.model2 = strzone(strcat("buff-", #sname)); \
- if(!Buff_Type_first) \
- Buff_Type_first = Buff_Type##sname; \
- if(Buff_Type_last) \
- Buff_Type_last.enemy = Buff_Type##sname; \
- Buff_Type_last = Buff_Type##sname; \
- } \
- ACCUMULATE_FUNCTION(RegisterBuffs, RegisterBuffs_##sname)
-
-REGISTER_BUFF(_("Ammo"),ammo,AMMO,3,'0.76 1 0.1');
-REGISTER_BUFF(_("Resistance"),resistance,RESISTANCE,0,'0.36 1 0.07');
-REGISTER_BUFF(_("Speed"),speed,SPEED,9,'0.1 1 0.84');
-REGISTER_BUFF(_("Medic"),medic,MEDIC,1,'1 0.12 0');
-REGISTER_BUFF(_("Bash"),bash,BASH,5,'1 0.39 0');
-REGISTER_BUFF(_("Vampire"),vampire,VAMPIRE,2,'1 0 0.24');
-REGISTER_BUFF(_("Disability"),disability,DISABILITY,7,'0.94 0.3 1');
-REGISTER_BUFF(_("Vengeance"),vengeance,VENGEANCE,15,'1 0.23 0.61');
-REGISTER_BUFF(_("Jump"),jump,JUMP,10,'0.24 0.78 1');
-REGISTER_BUFF(_("Flight"),flight,FLIGHT,11,'0.33 0.56 1');
-REGISTER_BUFF(_("Invisible"),invisible,INVISIBLE,12,'0.5 0.5 1');
-REGISTER_BUFF(_("Inferno"),inferno,INFERNO,16,'1 0.62 0');
-REGISTER_BUFF(_("Swapper"),swapper,SWAPPER,17,'0.63 0.36 1');
-REGISTER_BUFF(_("Magnet"),magnet,MAGNET,18,'1 0.95 0.18');
-#undef REGISTER_BUFF
+REGISTER_BUFF(INVISIBLE) {
+ this.m_prettyName = _("Invisible");
+ this.m_name = "invisible";
+ this.m_skin = 12;
+ this.m_color = '0.5 0.5 1';
+}
+
+REGISTER_BUFF(INFERNO) {
+ this.m_prettyName = _("Inferno");
+ this.m_name = "inferno";
+ this.m_skin = 16;
+ this.m_color = '1 0.62 0';
+}
+
+REGISTER_BUFF(SWAPPER) {
+ this.m_prettyName = _("Swapper");
+ this.m_name = "swapper";
+ this.m_skin = 17;
+ this.m_color = '0.63 0.36 1';
+}
+
+REGISTER_BUFF(MAGNET) {
+ this.m_prettyName = _("Magnet");
+ this.m_name = "magnet";
+ this.m_skin = 18;
+ this.m_color = '1 0.95 0.18';
+}
#ifdef SVQC
.int buffs;
void buff_Init(entity ent);
-void buff_Init_Compat(entity ent, int replacement);
+void buff_Init_Compat(entity ent, entity replacement);
-#define BUFF_SPAWNFUNC(e,b,t) void spawnfunc_item_buff_##e() { self.buffs = b; self.team = t; buff_Init(self); }
-#define BUFF_SPAWNFUNC_Q3TA_COMPAT(o,r) void spawnfunc_item_##o() { buff_Init_Compat(self,r); }
-#define BUFF_SPAWNFUNCS(e,b) \
- BUFF_SPAWNFUNC(e, b, 0) \
- BUFF_SPAWNFUNC(e##_team1, b, NUM_TEAM_1) \
- BUFF_SPAWNFUNC(e##_team2, b, NUM_TEAM_2) \
- BUFF_SPAWNFUNC(e##_team3, b, NUM_TEAM_3) \
- BUFF_SPAWNFUNC(e##_team4, b, NUM_TEAM_4)
+#define BUFF_SPAWNFUNC(e, b, t) void spawnfunc_item_buff_##e() { \
+ self.buffs = b.m_itemid; \
+ self.team = t; \
+ buff_Init(self); \
+}
+#define BUFF_SPAWNFUNCS(e, b) \
+ BUFF_SPAWNFUNC(e, b, 0) \
+ BUFF_SPAWNFUNC(e##_team1, b, NUM_TEAM_1) \
+ BUFF_SPAWNFUNC(e##_team2, b, NUM_TEAM_2) \
+ BUFF_SPAWNFUNC(e##_team3, b, NUM_TEAM_3) \
+ BUFF_SPAWNFUNC(e##_team4, b, NUM_TEAM_4)
+#define BUFF_SPAWNFUNC_Q3TA_COMPAT(o, r) void spawnfunc_item_##o() { buff_Init_Compat(self, r); }
BUFF_SPAWNFUNCS(resistance, BUFF_RESISTANCE)
BUFF_SPAWNFUNCS(ammo, BUFF_AMMO)
BUFF_SPAWNFUNCS(inferno, BUFF_INFERNO)
BUFF_SPAWNFUNCS(swapper, BUFF_SWAPPER)
BUFF_SPAWNFUNCS(magnet, BUFF_MAGNET)
-BUFF_SPAWNFUNCS(random, 0)
+BUFF_SPAWNFUNCS(random, BUFF_NULL)
BUFF_SPAWNFUNC_Q3TA_COMPAT(doubler, BUFF_MEDIC)
BUFF_SPAWNFUNC_Q3TA_COMPAT(resistance, BUFF_RESISTANCE)
#undef BUFF_SPAWNFUNCS
#endif
-vector Buff_Color(int buff_id);
-string Buff_PrettyName(int buff_id);
-string Buff_Name(int buff_id);
-int Buff_Type_FromName(string buff_name);
-int Buff_Type_FromSprite(string buff_sprite);
-int Buff_Skin(int buff_id);
-string Buff_Sprite(int buff_id);
-float Buff_Timer(int buff_id);
#endif
/** If you register a new item, make sure to add it to this list */
#include "item/ammo.qc"
#include "item/armor.qc"
-#include "item/buff.qc"
#include "item/health.qc"
#include "item/jetpack.qc"
#include "item/pickup.qc"
void Dump_Items()
{
- ITEMS_FOREACH(true, LAMBDA({
+ FOREACH(ITEMS, 0, ITEM_COUNT, true, LAMBDA({
ITEM_HANDLE(Show, it);
}));
}
#define REGISTER_ITEM(id, class) REGISTER(RegisterItems, ITEM, ITEMS, ITEM_COUNT, id, class, m_id)
REGISTER_REGISTRY(RegisterItems)
-#define ITEMS_FOREACH(pred, body) do { \
- for (int i = 0; i < ITEM_COUNT; i++) { \
- const noref entity it = ITEMS[i]; \
- if (pred) { body } \
- } \
-} while(0)
-
void Dump_Items();
#endif
void Inventory_Read(Inventory data)
{
const int bits = ReadInt24_t();
- ITEMS_FOREACH(bits & BIT(i), LAMBDA({
+ FOREACH(ITEMS, 0, ITEM_COUNT, bits & BIT(i), LAMBDA({
.int fld = inv_items[i];
int prev = data.(fld);
int next = data.(fld) = ReadByte();
void Inventory_Write(Inventory data)
{
int bits = 0;
- ITEMS_FOREACH(true, LAMBDA({
+ FOREACH(ITEMS, 0, ITEM_COUNT, true, LAMBDA({
.int fld = inv_items[i];
bits = BITSET(bits, BIT(i), data.inventory.(fld) != (data.inventory.(fld) = data.(fld)));
}));
WriteInt24_t(MSG_ENTITY, bits);
- ITEMS_FOREACH(bits & BIT(i), LAMBDA({
+ FOREACH(ITEMS, 0, ITEM_COUNT, bits & BIT(i), LAMBDA({
WriteByte(MSG_ENTITY, data.inv_items[i]);
}));
}
+++ /dev/null
-#include "buff.qh"
-
-REGISTER_ITEM(DefaultBuff, Buff);
+++ /dev/null
-#ifndef BUFF_H
-#define BUFF_H
-#include "pickup.qh"
-CLASS(Buff, Pickup)
- ATTRIB(Buff, m_name, string, "Buff")
-ENDCLASS(Buff)
-#endif
ARG_CASE(ARG_CS_SV, "spree_end", (autocvar_notification_show_sprees ? notif_arg_spree_inf(-1, "", "", f1) : "")) \
ARG_CASE(ARG_CS_SV, "spree_lost", (autocvar_notification_show_sprees ? notif_arg_spree_inf(-2, "", "", f1) : "")) \
ARG_CASE(ARG_CS_SV, "item_wepname", WEP_NAME(f1)) \
- ARG_CASE(ARG_CS_SV, "item_buffname", sprintf("%s%s", rgb_to_hexcolor(Buff_Color(f1)), Buff_PrettyName(f1))) \
- ARG_CASE(ARG_CS_SV, "f3buffname", sprintf("%s%s", rgb_to_hexcolor(Buff_Color(f3)), Buff_PrettyName(f3))) \
+ ARG_CASE(ARG_CS_SV, "item_buffname", sprintf("%s%s", rgb_to_hexcolor(BUFFS[f1].m_color), BUFFS[f1].m_prettyName)) \
+ ARG_CASE(ARG_CS_SV, "f3buffname", sprintf("%s%s", rgb_to_hexcolor(BUFFS[f3].m_color), BUFFS[f3].m_prettyName)) \
ARG_CASE(ARG_CS_SV, "item_wepammo", (s1 != "" ? sprintf(_(" with %s"), s1) : "")) \
ARG_CASE(ARG_DC, "item_centime", ftos(autocvar_notification_item_centerprinttime)) \
ARG_CASE(ARG_SV, "death_team", Team_ColoredFullName(f1)) \
RaceCarPhysics();
#endif
- else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY || self.movetype == MOVETYPE_FLY_WORLDONLY || (BUFFS(self) & BUFF_FLIGHT))
+ else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY || self.movetype == MOVETYPE_FLY_WORLDONLY || (BUFFS_STAT(self) & BUFF_FLIGHT.m_itemid))
PM_fly(maxspeed_mod);
else if (self.waterlevel >= WATERLEVEL_SWIMMING)
#define WAS_ONGROUND(s) !!(s.lastflags & FL_ONGROUND)
#define ITEMS_STAT(s) (s).items
- #define BUFFS(s) getstati(STAT_BUFFS)
+ #define BUFFS_STAT(s) getstati(STAT_BUFFS)
#define PHYS_AMMO_FUEL(s) getstati(STAT_FUEL)
#define WAS_ONGROUND(s) !!((s).lastflags & FL_ONGROUND)
#define ITEMS_STAT(s) s.items
- #define BUFFS(s) (s).buffs
+ #define BUFFS_STAT(s) (s).buffs
#define PHYS_AMMO_FUEL(s) s.ammo_fuel
#ifndef REGISTRY_H
#define REGISTRY_H
+#include "oo.qh"
+
#define REGISTER_INIT(ns, id) [[accumulate]] void Register_##ns##_##id##_init(entity this)
+#define REGISTER_INIT_POST(ns, id) [[accumulate]] void Register_##ns##_##id##_init_post(entity this)
#define REGISTER(initfunc, ns, array, counter, id, class, fld) \
entity ns##_##id; \
REGISTER_INIT(ns, id) { } \
+ REGISTER_INIT_POST(ns, id) { } \
void Register_##ns##_##id() { \
entity this = NEW(class); \
ns##_##id = this; \
this.fld = counter; \
array[counter++] = this; \
Register_##ns##_##id##_init(this); \
+ Register_##ns##_##id##_init_post(this); \
} \
ACCUMULATE_FUNCTION(initfunc, Register_##ns##_##id) \
REGISTER_INIT(ns, id)
[[deprecated("use true")]] [[alias("true")]] const bool TRUE;
[[deprecated("use false")]] [[alias("false")]] const bool FALSE;
+#define FOREACH(arr, start, end, cond, body) do { \
+ for (int i = start; i < end; ++i) { \
+ const noref entity it = arr[i]; \
+ if (cond) { body } \
+ } \
+} while(0)
+
#ifdef GMQCC
#define OVERLOAD(F, ...) F##_##__VA_COUNT__(__VA_ARGS__)
#else
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
- CALL_ACCUMULATED_FUNCTION(RegisterBuffs);
MapInfo_Enumerate();
MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
- CALL_ACCUMULATED_FUNCTION(RegisterBuffs);
ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
#include "../../common/buffs.qh"
+entity buff_FirstFromFlags(int _buffs)
+{
+ if (flags)
+ {
+ FOREACH(BUFFS, 0, BUFFS_COUNT,
+ it.m_itemid & _buffs,
+ LAMBDA({
+ return it;
+ })
+ );
+ }
+ return BUFF_NULL;
+}
+
float buffs_BuffModel_Customize()
{
entity player, myowner;
vector buff_GlowColor(entity buff)
{
//if(buff.team) { return Team_ColorRGB(buff.team); }
- return buff.color;
+ return buff.m_color;
}
void buff_Effect(entity player, string eff)
// buff item
float buff_Waypoint_visible_for_player(entity plr)
{
- if(!self.owner.buff_active && !self.owner.buff_activetime)
- return false;
+ if(!self.owner.buff_active && !self.owner.buff_activetime)
+ return false;
- if(plr.buffs)
+ if (plr.buffs)
{
- if(plr.cvar_cl_buffs_autoreplace)
- {
- if(plr.buffs == self.owner.buffs)
- return false;
- }
- else
- return false;
+ return plr.cvar_cl_buffs_autoreplace == false || plr.buffs != self.owner.buffs;
}
- return WaypointSprite_visible_for_player(plr);
+ return WaypointSprite_visible_for_player(plr);
}
void buff_Waypoint_Spawn(entity e)
{
- WaypointSprite_Spawn(Buff_Sprite(e.buffs), 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_POWERUP, e.glowmod);
- WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_POWERUP, e.glowmod);
- e.buff_waypoint.waypointsprite_visible_for_player = buff_Waypoint_visible_for_player;
+ entity buff = buff_FirstFromFlags(e.buffs);
+ WaypointSprite_Spawn(buff.m_sprite, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_POWERUP, e.glowmod);
+ WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_POWERUP, e.glowmod);
+ e.buff_waypoint.waypointsprite_visible_for_player = buff_Waypoint_visible_for_player;
}
void buff_SetCooldown(float cd)
return;
}
- if(other.buffs)
+ if (other.buffs)
{
- if(other.cvar_cl_buffs_autoreplace && other.buffs != self.buffs)
+ if (other.cvar_cl_buffs_autoreplace && other.buffs != self.buffs)
{
+ int buffid = buff_FirstFromFlags(other.buffs).m_id;
//Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_BUFF_DROP, other.buffs);
- Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ITEM_BUFF_LOST, other.netname, other.buffs);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ITEM_BUFF_LOST, other.netname, buffid);
other.buffs = 0;
//sound(other, CH_TRIGGER, "relics/relic_effect.wav", VOL_BASE, ATTN_NORM);
self.owner = other;
self.buff_active = false;
self.lifetime = 0;
-
- Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_BUFF_GOT, self.buffs);
- Send_Notification(NOTIF_ALL_EXCEPT, other, MSG_INFO, INFO_ITEM_BUFF, other.netname, self.buffs);
+ int buffid = buff_FirstFromFlags(self.buffs).m_id;
+ Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_BUFF_GOT, buffid);
+ Send_Notification(NOTIF_ALL_EXCEPT, other, MSG_INFO, INFO_ITEM_BUFF, other.netname, buffid);
pointparticles(particleeffectnum("item_pickup"), CENTER_OR_VIEWOFS(self), '0 0 0', 1);
sound(other, CH_TRIGGER, "misc/shield_respawn.wav", VOL_BASE, ATTN_NORM);
other.buffs |= (self.buffs);
}
-float buff_Available(float buffid)
+float buff_Available(entity buff)
{
- if(buffid == BUFF_AMMO && ((start_items & IT_UNLIMITED_WEAPON_AMMO) || (start_items & IT_UNLIMITED_AMMO) || (cvar("g_melee_only"))))
+ if (buff == BUFF_NULL)
return false;
-
- if(buffid == BUFF_VAMPIRE && cvar("g_vampire"))
+ if (buff == BUFF_AMMO && ((start_items & IT_UNLIMITED_WEAPON_AMMO) || (start_items & IT_UNLIMITED_AMMO) || (cvar("g_melee_only"))))
return false;
-
- if(!cvar(strcat("g_buffs_", Buff_Name(buffid))))
+ if (buff == BUFF_VAMPIRE && cvar("g_vampire"))
return false;
-
- return true;
+ return cvar(strcat("g_buffs_", buff.m_name));
}
+.int buff_seencount;
+
void buff_NewType(entity ent, float cb)
{
- entity e;
RandomSelection_Init();
- for(e = Buff_Type_first; e; e = e.enemy)
- if(buff_Available(e.items))
- {
- RandomSelection_Add(world, e.items, string_null, 1, max(0.2, 1 / e.count)); // if it's already been chosen, give it a lower priority
- e.count += 1;
- }
+ FOREACH(BUFFS, 0, BUFFS_COUNT,
+ buff_Available(it),
+ LAMBDA({
+ it.buff_seencount += 1;
+ // if it's already been chosen, give it a lower priority
+ RandomSelection_Add(world, it.m_itemid, string_null, 1, max(0.2, 1 / it.buff_seencount));
+ })
+ );
ent.buffs = RandomSelection_chosen_float;
}
{
if(self.buffs != self.oldbuffs)
{
- self.color = Buff_Color(self.buffs);
- self.glowmod = buff_GlowColor(self);
- self.skin = Buff_Skin(self.buffs);
+ entity buff = buff_FirstFromFlags(self.buffs);
+ self.color = buff.m_color;
+ self.glowmod = buff_GlowColor(buff);
+ self.skin = buff.m_skin;
setmodel(self, BUFF_MODEL);
{
buff_SetCooldown(self.buff_activetime);
self.buff_activetime_updated = true;
- }
+ }
if(!self.buff_active && !self.buff_activetime)
if(!self.owner || self.owner.frozen || self.owner.deadflag != DEAD_NO || !self.owner.iscreature || !(self.owner.buffs & self.buffs))
if(!teamplay && ent.team) { ent.team = 0; }
+ entity buff = buff_FirstFromFlags(self.buffs);
+
entity oldself = self;
self = ent;
- if(!self.buffs || buff_Available(self.buffs))
+ if(!self.buffs || buff_Available(buff))
buff_NewType(self, 0);
self.classname = "item_buff";
self.gravity = 1;
self.movetype = MOVETYPE_TOSS;
self.scale = 1;
- self.skin = Buff_Skin(self.buffs);
+ self.skin = buff.m_skin;
self.effects = EF_FULLBRIGHT | EF_STARDUST | EF_NOSHADOW;
self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY;
self.customizeentityforclient = buff_Customize;
//self.gravity = 100;
- self.color = Buff_Color(self.buffs);
+ self.color = buff.m_color;
self.glowmod = buff_GlowColor(self);
buff_SetCooldown(autocvar_g_buffs_cooldown_activate + game_starttime);
self.buff_active = !self.buff_activetime;
self = oldself;
}
-void buff_Init_Compat(entity ent, float replacement)
+void buff_Init_Compat(entity ent, entity replacement)
{
- if(ent.spawnflags & 2)
+ if (ent.spawnflags & 2)
ent.team = NUM_TEAM_1;
- else if(ent.spawnflags & 4)
+ else if (ent.spawnflags & 4)
ent.team = NUM_TEAM_2;
- ent.buffs = replacement;
+ ent.buffs = replacement.m_itemid;
buff_Init(ent);
}
{
if(frag_deathtype == DEATH_BUFF) { return false; }
- if(frag_target.buffs & BUFF_RESISTANCE)
+ if(frag_target.buffs & BUFF_RESISTANCE.m_itemid)
{
vector v = healtharmor_applydamage(50, autocvar_g_buffs_resistance_blockpercent, frag_deathtype, frag_damage);
damage_take = v.x;
{
if(frag_deathtype == DEATH_BUFF) { return false; }
- if(frag_target.buffs & BUFF_SPEED)
+ if(frag_target.buffs & BUFF_SPEED.m_itemid)
if(frag_target != frag_attacker)
frag_damage *= autocvar_g_buffs_speed_damage_take;
- if(frag_target.buffs & BUFF_MEDIC)
+ if(frag_target.buffs & BUFF_MEDIC.m_itemid)
if((frag_target.health - frag_damage) <= 0)
if(!ITEM_DAMAGE_NEEDKILL(frag_deathtype))
if(frag_attacker)
if(random() <= autocvar_g_buffs_medic_survive_chance)
frag_damage = max(5, frag_target.health - autocvar_g_buffs_medic_survive_health);
- if(frag_target.buffs & BUFF_JUMP)
+ if(frag_target.buffs & BUFF_JUMP.m_itemid)
if(frag_deathtype == DEATH_FALL)
frag_damage = 0;
- if(frag_target.buffs & BUFF_VENGEANCE)
+ if(frag_target.buffs & BUFF_VENGEANCE.m_itemid)
if(frag_attacker)
if(frag_attacker != frag_target)
if(!ITEM_DAMAGE_NEEDKILL(frag_deathtype))
dmgent.nextthink = time + 0.1;
}
- if(frag_target.buffs & BUFF_BASH)
+ if(frag_target.buffs & BUFF_BASH.m_itemid)
if(frag_attacker != frag_target)
if(vlen(frag_force))
frag_force = '0 0 0';
- if(frag_attacker.buffs & BUFF_BASH)
+ if(frag_attacker.buffs & BUFF_BASH.m_itemid)
if(vlen(frag_force))
if(frag_attacker == frag_target)
frag_force *= autocvar_g_buffs_bash_force_self;
else
frag_force *= autocvar_g_buffs_bash_force;
- if(frag_attacker.buffs & BUFF_DISABILITY)
+ if(frag_attacker.buffs & BUFF_DISABILITY.m_itemid)
if(frag_target != frag_attacker)
frag_target.buff_disability_time = time + autocvar_g_buffs_disability_slowtime;
- if(frag_attacker.buffs & BUFF_MEDIC)
+ if(frag_attacker.buffs & BUFF_MEDIC.m_itemid)
if(DEATH_WEAPONOF(frag_deathtype) != WEP_ARC)
if(SAME_TEAM(frag_attacker, frag_target))
if(frag_attacker != frag_target)
frag_damage = 0;
}
- if(frag_attacker.buffs & BUFF_INFERNO)
+ if(frag_attacker.buffs & BUFF_INFERNO.m_itemid)
if(frag_target != frag_attacker) {
float time = buff_Inferno_CalculateTime(
frag_damage,
}
// this... is ridiculous (TODO: fix!)
- if(frag_attacker.buffs & BUFF_VAMPIRE)
+ if(frag_attacker.buffs & BUFF_VAMPIRE.m_itemid)
if(!frag_target.vehicle)
if(DEATH_WEAPONOF(frag_deathtype) != WEP_ARC)
if(!ITEM_DAMAGE_NEEDKILL(frag_deathtype))
MUTATOR_HOOKFUNCTION(buffs_PlayerPhysics)
{
- if(self.buffs & BUFF_SPEED)
+ if(self.buffs & BUFF_SPEED.m_itemid)
{
self.stat_sv_maxspeed *= autocvar_g_buffs_speed_speed;
self.stat_sv_airspeedlimit_nonqw *= autocvar_g_buffs_speed_speed;
self.stat_sv_airspeedlimit_nonqw *= autocvar_g_buffs_disability_speed;
}
- if(self.buffs & BUFF_JUMP)
+ if(self.buffs & BUFF_JUMP.m_itemid)
{
// automatically reset, no need to worry
self.stat_sv_jumpvelocity = autocvar_g_buffs_jump_height;
MUTATOR_HOOKFUNCTION(buffs_PlayerJump)
{
- if(self.buffs & BUFF_JUMP)
+ if(self.buffs & BUFF_JUMP.m_itemid)
player_jumpheight = autocvar_g_buffs_jump_height;
return false;
{
if(self.buffs)
{
- Send_Notification(NOTIF_ALL_EXCEPT, self, MSG_INFO, INFO_ITEM_BUFF_LOST, self.netname, self.buffs);
+ int buffid = buff_FirstFromFlags(self.buffs).m_id;
+ Send_Notification(NOTIF_ALL_EXCEPT, self, MSG_INFO, INFO_ITEM_BUFF_LOST, self.netname, buffid);
self.buffs = 0;
if(self.buff_model)
if(MUTATOR_RETURNVALUE || gameover) { return false; }
if(self.buffs)
{
- Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_BUFF_DROP, self.buffs);
- Send_Notification(NOTIF_ALL_EXCEPT, self, MSG_INFO, INFO_ITEM_BUFF_LOST, self.netname, self.buffs);
+ int buffid = buff_FirstFromFlags(self.buffs).m_id;
+ Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_BUFF_DROP, buffid);
+ Send_Notification(NOTIF_ALL_EXCEPT, self, MSG_INFO, INFO_ITEM_BUFF_LOST, self.netname, buffid);
self.buffs = 0;
sound(self, CH_TRIGGER, "relics/relic_effect.wav", VOL_BASE, ATTN_NORM);
{
if(MUTATOR_RETURNVALUE || gameover) { return false; }
- if(self.buffs & BUFF_SWAPPER)
+ if(self.buffs & BUFF_SWAPPER.m_itemid)
{
float best_distance = autocvar_g_buffs_swapper_range;
entity closest = world;
// if you have the invisibility powerup, sprites ALWAYS are restricted to your team
// but only apply this to real players, not to spectators
- if((self.owner.flags & FL_CLIENT) && (self.owner.buffs & BUFF_INVISIBLE) && (e == other))
+ if((self.owner.flags & FL_CLIENT) && (self.owner.buffs & BUFF_INVISIBLE.m_itemid) && (e == other))
if(DIFF_TEAM(self.owner, e))
return true;
MUTATOR_HOOKFUNCTION(buffs_WeaponRate)
{
- if(self.buffs & BUFF_SPEED)
+ if(self.buffs & BUFF_SPEED.m_itemid)
weapon_rate *= autocvar_g_buffs_speed_rate;
if(time < self.buff_disability_time)
MUTATOR_HOOKFUNCTION(buffs_WeaponSpeed)
{
- if(self.buffs & BUFF_SPEED)
+ if(self.buffs & BUFF_SPEED.m_itemid)
ret_float *= autocvar_g_buffs_speed_weaponspeed;
if(time < self.buff_disability_time)
return false;
}
+.float buff_time;
+
MUTATOR_HOOKFUNCTION(buffs_PlayerThink)
{
if(gameover || self.deadflag != DEAD_NO) { return false; }
{
if(self.buffs)
{
- Send_Notification(NOTIF_ALL_EXCEPT, self, MSG_INFO, INFO_ITEM_BUFF_LOST, self.netname, self.buffs);
+ int buffid = buff_FirstFromFlags(self.buffs).m_id;
+ Send_Notification(NOTIF_ALL_EXCEPT, self, MSG_INFO, INFO_ITEM_BUFF_LOST, self.netname, buffid);
if(buff_lost >= 2)
{
- Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_BUFF_DROP, self.buffs); // TODO: special timeout message?
+ Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_BUFF_DROP, buffid); // TODO: special timeout message?
sound(self, CH_TRIGGER, "relics/relic_effect.wav", VOL_BASE, ATTN_NORM);
}
self.buffs = 0;
}
}
- if(self.buffs & BUFF_MAGNET)
+ if(self.buffs & BUFF_MAGNET.m_itemid)
{
vector pickup_size = '1 1 1' * autocvar_g_buffs_magnet_range_item;
for(other = world; (other = findflags(other, flags, FL_ITEM)); )
}
}
- if(self.buffs & BUFF_AMMO)
+ if(self.buffs & BUFF_AMMO.m_itemid)
if(self.clip_size)
self.clip_load = self.(weapon_load[self.switchweapon]) = self.clip_size;
- if((self.buffs & BUFF_INVISIBLE) && (self.oldbuffs & BUFF_INVISIBLE))
+ if((self.buffs & BUFF_INVISIBLE.m_itemid) && (self.oldbuffs & BUFF_INVISIBLE.m_itemid))
if(self.alpha != autocvar_g_buffs_invisible_alpha)
self.alpha = autocvar_g_buffs_invisible_alpha; // powerups reset alpha, so we must enforce this (TODO)
-#define BUFF_ONADD(b) if((self.buffs & (b)) && !(self.oldbuffs & (b)))
-#define BUFF_ONREM(b) if(!(self.buffs & (b)) && (self.oldbuffs & (b)))
+#define BUFF_ONADD(b) if ( (self.buffs & (b).m_itemid) && !(self.oldbuffs & (b).m_itemid))
+#define BUFF_ONREM(b) if (!(self.buffs & (b).m_itemid) && (self.oldbuffs & (b).m_itemid))
if(self.buffs != self.oldbuffs)
{
- if(self.buffs && Buff_Timer(self.buffs))
- self.buff_time = time + Buff_Timer(self.buffs);
- else
- self.buff_time = 0;
+ entity buff = buff_FirstFromFlags(self.buffs);
+ float bufftime = buff != BUFF_NULL ? buff.m_time(buff) : 0;
+ self.buff_time = (bufftime) ? time + bufftime : 0;
BUFF_ONADD(BUFF_AMMO)
{
if(!self.buff_model)
buffs_BuffModel_Spawn(self);
- self.buff_model.color = Buff_Color(self.buffs);
+ self.buff_model.color = buff.m_color;
self.buff_model.glowmod = buff_GlowColor(self.buff_model);
- self.buff_model.skin = Buff_Skin(self.buffs);
+ self.buff_model.skin = buff.m_skin;
self.effects |= EF_NOSHADOW;
}
MUTATOR_HOOKFUNCTION(buffs_PlayerRegen)
{
- if(self.buffs & BUFF_MEDIC)
+ if(self.buffs & BUFF_MEDIC.m_itemid)
{
regen_mod_rot = autocvar_g_buffs_medic_rot;
regen_mod_limit = regen_mod_max = autocvar_g_buffs_medic_max;
regen_mod_regen = autocvar_g_buffs_medic_regen;
}
- if(self.buffs & BUFF_SPEED)
+ if(self.buffs & BUFF_SPEED.m_itemid)
regen_mod_regen = autocvar_g_buffs_speed_regen;
return false;
frag_mirrordamage = 0;
}
- if((frag_target.buffs & BUFF_INVISIBLE) || (frag_target.items & IT_STRENGTH))
+ if((frag_target.buffs & BUFF_INVISIBLE.m_itemid) || (frag_target.items & IT_STRENGTH))
yoda = 1;
return false;